Übung: Beheben eines fehlgeschlagenen Tests

Abgeschlossen

Nun können Sie Komponententests ausführen, während Änderungen ihren Weg durch die Buildpipeline nehmen. Sie verfügen auch über eine Möglichkeit, zu messen, wie viel Code von Ihren Tests abgedeckt wird.

Es empfiehlt sich, dass Sie Ihre Tests lokal ausführen, bevor Sie Änderungen an die Pipeline übermitteln. Aber was passiert, wenn das jemand vergisst und eine Änderung übermittelt, die den Build beschädigt?

In dieser Lerneinheit korrigieren Sie einen fehlerhaften Build, der durch einen nicht bestandenen Komponententest verursacht wurde. Hierzu gehen Sie wie folgt vor:

  • Abrufen des Startercodes von GitHub
  • Hinzufügen von Code Coverage-Tools zum Projekt
  • Übertragen des Codes mithilfe von Push an Ihr Repository
  • Automatische Ausführung der Pipeline und Fehlschlagen der Komponententests
  • Lokales Reproduzieren des Fehlers
  • Analysieren und Beheben des Fehlers
  • Übertragen einer Fehlerbehebung mithilfe von Push und erfolgreicher Build

Überprüfen des neuen Komponententests

Das neueste Feature des Teams umfasst die Bestenliste. Wir müssen die Punktezahl aus der Datenbank abrufen, sodass wir einen Komponententest schreiben können, um die IDocumentDBRepository<T>.GetItemsAsync-Methode zu überprüfen.

Der Test sieht wie folgt aus. Sie müssen jetzt noch keinen Code hinzufügen.

[TestCase(0, ExpectedResult=0)]
[TestCase(1, ExpectedResult=1)]
[TestCase(10, ExpectedResult=10)]
public int ReturnRequestedCount(int count)
{
    const int PAGE = 0; // take the first page of results

    // Fetch the scores.
    Task<IEnumerable<Score>> scoresTask = _scoreRepository.GetItemsAsync(
        score => true, // return all scores
        score => 1, // we don't care about the order
        PAGE,
        count // fetch this number of results
    );
    IEnumerable<Score> scores = scoresTask.Result;

    // Verify that we received the specified number of items.
    return scores.Count();
}

Denken Sie daran, dass TestCase in einem NUnit-Test Inlinedaten zum Testen der betreffenden Methode bereitstellt. NUnit ruft die Komponententestmethode ReturnRequestedCount folgendermaßen auf:

ReturnRequestedCount(0);
ReturnRequestedCount(1);
ReturnRequestedCount(10);

Dieser Test verwendet auch die ExpectedResult-Eigenschaft, um den Testcode zu vereinfachen und die Testabsicht zu verdeutlichen. NUnit vergleicht den Rückgabewert automatisch mit dem Wert dieser Eigenschaft, sodass die Assert-Anweisung nicht explizit aufgerufen werden muss.

Wir wählen einige Werte aus, die typische Abfragen darstellen. Wir schließen auch 0 ein, um diesen Grenzfall abzudecken.

Abrufen des Branchs aus GitHub

Wie zuvor rufen Sie den Branch failed-test aus GitHub ab und checken ihn aus oder wechseln zu ihm.

  1. Öffnen Sie in Visual Studio Code das integrierte Terminal.

  2. Führen Sie die folgenden git fetch- und git checkout-Befehle aus, um einen Branch namens failed-test aus dem Microsoft-Repository herunterzuladen, und wechseln Sie zu diesem Branch:

    git fetch upstream failed-test
    git checkout -B failed-test upstream/failed-test
    

    Für diese Übung haben wir den Branch failed-test genannt. In der Praxis würden Sie ein Branch dem Zweck oder Feature entsprechend benennen.

  3. Führen Sie die folgenden Befehle aus, um eine lokale Toolmanifestdatei zu erstellen, das ReportGenerator-Tool zu installieren und das coverlet.msbuild-Paket zum Testprojekt hinzuzufügen:

    dotnet new tool-manifest
    dotnet tool install dotnet-reportgenerator-globaltool
    dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
    

    Dieser Schritt ist erforderlich, weil der Branch failed-test nicht die Arbeit enthält, die Sie dem Branch unit-tests hinzugefügt haben.

  4. Fügen Sie die Testprojektdatei und die Toolmanifestdatei zum Stagingindex hinzu, und committen Sie die Änderungen.

    git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj
    git add .config/dotnet-tools.json
    git commit -m "Configure code coverage tests"
    
  5. Führen Sie den folgenden git push-Befehl aus, um den Branch failed-test in Ihr GitHub-Repository hochzuladen:

    git push origin failed-test
    

Anzeigen des Testfehlschlags in der Pipeline

Angenommen, Sie waren in Eile und haben Ihre Arbeit gepusht, ohne die Tests ein letztes Mal durchzuführen. Glücklicherweise kann die Pipeline Ihnen helfen, Probleme frühzeitig abzufangen, wenn Komponententests vorhanden sind. Das werden wir Ihnen hier zeigen.

  1. Verfolgen Sie in Azure Pipelines den Build, wenn er die Pipeline durchläuft.

  2. Erweitern Sie die Aufgabe Run unit tests - Release, während sie ausgeführt wird.

    Sie sehen, dass die ReturnRequestedCount-Testmethode fehlschlägt.

    Screenshot des Azure Pipelines-Dashboards mit dem Ausgabeprotokoll eines Assertionsfehlers im Komponententest, bei dem 10 erwartet, aber 9 zurückgegeben wurde.

    Der Test wird bestanden, wenn der Eingabewert 0 ist, schlägt aber fehl, wenn der Eingabe Wert 1 oder 10 ist.

    Der Build wird erst dann in der Pipeline veröffentlicht, wenn die vorherige Aufgabe erfolgreich durchgeführt wurde. Hier wurde der Build nicht veröffentlicht, weil die Komponententests fehlgeschlagen sind. Dadurch wird verhindert, dass andere versehentlich einen fehlerhaften Build erhalten.

In der Praxis werden Sie den Build während der Ausführung nicht immer manuell nachverfolgen. Nachstehend sind einige Möglichkeiten aufgeführt, wie der Fehler erkannt werden kann:

  • E-Mail-Benachrichtigung von Azure DevOps

    Sie können Azure DevOps so konfigurieren, dass eine E-Mail-Benachrichtigung gesendet wird, wenn der Build beendet ist. Die Betreffzeile beginnt mit "[Build failed]", wenn der Build fehlschlägt.

    Screenshot mit einem Teil einer E-Mail-Benachrichtigung für einen fehlgeschlagenen Build.

  • Azure Test Plans

    Wählen Sie in Azure DevOps Test Plans und dann Runs aus. Die letzten Testläufe, einschließlich des soeben ausgeführten Testlaufs, werden angezeigt. Wählen Sie den letzten abgeschlossenen Test aus. Sie sehen, dass zwei der acht Tests fehlgeschlagen sind.

    Screenshot des Azure DevOps-Testlaufergebnisses mit einem Ringdiagramm, in dem angezeigt wird, dass zwei von acht Tests fehlgeschlagen sind.

  • Das Dashboard

    Wählen Sie in Azure DevOps Overview und dann Dashboards aus. Der Fehler wird im Widget Test Results Trend angezeigt. Das Code Coverage-Widget ist leer, was darauf hinweist, dass kein Code Coverage-Test ausgeführt wurde.

    Screenshot des Trenddiagramm-Widgets im Azure DevOps-Dashboard mit zwei fehlgeschlagenen Tests im letzten Testlauf.

  • Der Build-Badge

    Obwohl der failed-test-Branch keinen Build-Badge in der README.md-Datei enthält, würde auf GitHub Folgendes angezeigt, wenn der Build fehlschlägt:

    Screenshot des Build-Badges von Azure Pipelines auf GitHub, der auf einen Fehler hinweist.

Analysieren des Testfehler

Wenn Komponententests fehlschlagen, haben Sie je nach Fehler normalerweise zwei Möglichkeiten:

  • Wenn der Test einen Fehler im Code aufzeigt, korrigieren Sie den Code und führen die Tests erneut aus.
  • Wenn sich die Funktionalität geändert hat, passen Sie den Test so an, dass er den neuen Anforderungen entspricht.

Lokales Reproduzieren des Fehlers

In diesem Abschnitt reproduzieren Sie den Fehler lokal.

  1. Öffnen Sie in Visual Studio Code das integrierte Terminal.

  2. Führen Sie im Terminal diesen dotnet build-Befehl aus, um die Anwendung zu kompilieren:

    dotnet build --configuration Release
    
  3. Führen Sie im Terminal diesen dotnet test-Befehl aus, um die Komponententests auszuführen:

    dotnet test --no-build --configuration Release
    

    Ihnen sollten dieselben Fehler angezeigt werden, die auch in der Pipeline angezeigt wurden. Hier sehen Sie einen Teil der Ausgabe:

    Starting test execution, please wait...
    A total of 1 test files matched the specified pattern.
      Failed ReturnRequestedCount(1) [33 ms]
      Error Message:
         Expected: 1
      But was:  0
    
      Stack Trace:
         at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
       at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0()
       at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action)
    
      Failed ReturnRequestedCount(10) [1 ms]
      Error Message:
         Expected: 10
      But was:  9
    
      Stack Trace:
         at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
       at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0()
       at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action)
    
    
    Failed!  - Failed:     2, Passed:     6, Skipped:     0, Total:     8, Duration: 98 ms
    

Suchen der Fehlerursache

Sie bemerken, dass jeder fehlgeschlagene Test ein um eins abweichendes Ergebnis erzeugt. Wenn z. B. 10 erwartet wird, gibt der Test 9 zurück.

Sie sehen sich den Quellcode für die getestete Methode LocalDocumentDBRepository<T>.GetItemsAsync an. Folgendes sollte angezeigt werden:

public Task<IEnumerable<T>> GetItemsAsync(
    Func<T, bool> queryPredicate,
    Func<T, int> orderDescendingPredicate,
    int page = 1, int pageSize = 10
)
{
    var result = _items
        .Where(queryPredicate) // filter
        .OrderByDescending(orderDescendingPredicate) // sort
        .Skip(page * pageSize) // find page
        .Take(pageSize - 1); // take items

    return Task<IEnumerable<T>>.FromResult(result);
}

In diesem Szenario könnten Sie GitHub überprüfen, um zu nachzusehen, ob die Datei kürzlich geändert wurde.

Screenshot von GitHub mit einem Dateivergleich, der aufzeigt, dass eine „minus eins“-Operation hinzugefügt wurde.

Sie vermuten, dass pageSize - 1 ein um eins kleineres Ergebnis zurückgibt und der Code lediglich pageSize lauten sollte. In unserem Szenario ist dies ein Fehler, den Sie beim Pushen ohne Tests ausgeführt haben, aber in einem realen Szenario können Sie sich bei dem Entwickler erkundigen, der die Datei auf GitHub geändert hat, um den Grund für die Änderung zu ermitteln.

Tipp

Diskussion und Zusammenarbeit sind auch auf GitHub möglich. Sie können einen Pull Request kommentieren oder eine Problemdiskussion eröffnen.

Beheben des Fehlers

In diesem Abschnitt beheben Sie den Fehler, indem Sie den Code wieder in seinen ursprünglichen Zustand zurück versetzen und die Tests ausführen, um die Korrektur zu überprüfen.

  1. Öffnen Sie in Visual Studio Code Tailspin.SpaceGame.Web/LocalDocumentDBRepository.cs im Datei-Explorer.

  2. Ändern Sie die GetItemsAsync-Methode wie hier gezeigt:

    public Task<IEnumerable<T>> GetItemsAsync(
        Func<T, bool> queryPredicate,
        Func<T, int> orderDescendingPredicate,
        int page = 1, int pageSize = 10
    )
    {
        var result = _items
            .Where(queryPredicate) // filter
            .OrderByDescending(orderDescendingPredicate) // sort
            .Skip(page * pageSize) // find page
            .Take(pageSize); // take items
    
        return Task<IEnumerable<T>>.FromResult(result);
    }
    

    Diese Version ändert pageSize - 1 in pageSize.

  3. Speichern Sie die Datei .

  4. Kompilieren Sie die Anwendung im integrierten Terminal.

    dotnet build --configuration Release
    

    Sie sollten sehen, dass der Build erfolgreich ist.

    In der Praxis können Sie die App ausführen und kurz ausprobieren. Im Rahmen dieser Übung verzichten wir darauf.

  5. Führen Sie die Komponententests im Terminal aus.

    dotnet test --no-build --configuration Release
    

    Sie sehen, dass die Tests erfolgreich durchgeführt werden.

    Starting test execution, please wait...
    A total of 1 test files matched the specified pattern.
    
    Passed!  - Failed:     0, Passed:     8, Skipped:     0, Total:     8, Duration: 69 ms
    
  6. Fügen Sie alle geänderten Dateien im integrierten Terminal zum Index hinzu, committen Sie die Änderungen, und pushen Sie den Branch an GitHub.

    git add .
    git commit -m "Return correct number of items"
    git push origin failed-test
    

    Tipp

    Der Punkt (.) in diesem git add-Beispiel ist ein Platzhalterzeichen. Er steht für alle ungestageten Dateien im aktuellen Verzeichnis und allen Unterverzeichnissen.

    Bevor Sie dieses Platzhalterzeichen verwenden, sollten Sie git status ausführen bevor sich sich festlegen, um sicherzustellen, dass Sie die tatsächlich die gewünschten Dateien stagen.

  7. Kehren Sie zu Azure Pipelines zurück. Beobachten Sie, wie die Änderung die Pipeline durchläuft. Die Tests werden bestanden, und der gesamte Buildvorgang ist erfolgreich.

    Zum Überprüfen der Testergebnisse können Sie optional die Registerkarten Tests und Code Coverage auswählen, nachdem der Buildvorgang abgeschlossen wurde.

    Sie können den aktualisierten Ergebnistrend auch im Dashboard überprüfen.

    Screenshot des Trenddiagramms im Azure DevOps-Dashboard, in dem angezeigt wird, dass wieder alle Tests bestandenen wurden.

Großartig! Sie haben den Build korrigiert. Als Nächstes erfahren Sie, wie Sie Ihre Azure DevOps-Umgebung bereinigen.