Oefening: een mislukte test oplossen

Voltooid

Op dit moment hebt u een manier om eenheidstests uit te voeren wanneer wijzigingen door de build-pijplijn lopen. U hebt ook een manier om de hoeveelheid code te meten die wordt gedekt door uw tests.

Het is altijd een goed idee om uw tests lokaal uit te voeren voordat u wijzigingen in de pijplijn indient. Maar wat gebeurt er wanneer iemand een wijziging vergeet en verzendt die de build onderbreekt?

In deze eenheid lost u een verbroken build op die wordt veroorzaakt door een mislukte eenheidstest. Hier gaat u het volgende doen:

  • Starterscode ophalen uit GitHub.
  • Voeg hulpprogramma's voor codedekking toe aan uw project.
  • Push de code naar uw opslagplaats.
  • Bekijk hoe de pijplijn automatisch wordt uitgevoerd en de eenheidstests mislukken.
  • Reproduceer de fout lokaal.
  • Analyseer en los de fout op.
  • Push een oplossing en bekijk hoe de build slaagt.

De nieuwe eenheidstest controleren

De nieuwste functie van het team omvat het leaderboard. We moeten het aantal scores uit de database ophalen, zodat we een eenheidstest kunnen schrijven om de IDocumentDBRepository<T>.GetItemsAsync methode te verifiëren.

Zo ziet de test eruit. U hoeft nog geen code toe te voegen.

[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();
}

Zoals u weet, TestCase biedt in een NUnit-test inlinegegevens die moeten worden gebruikt om die methode te testen. NUnit roept de ReturnRequestedCount eenheidstestmethode als volgt aan:

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

Deze test maakt ook gebruik van de ExpectedResult eigenschap om de testcode te vereenvoudigen en de bedoeling ervan duidelijk te maken. NUnit vergelijkt automatisch de retourwaarde met de waarde van deze eigenschap, zodat de noodzaak om de assertie expliciet aan te roepen, wordt verwijderd.

We kiezen een aantal waarden die typische query's vertegenwoordigen. We nemen ook 0 op om die randcase te bedekken.

De branch ophalen vanuit GitHub

Zoals u eerder hebt gedaan, haalt u de failed-test vertakking op uit GitHub en checkt u die vertakking uit (of schakelt u over naar).

  1. Open in Visual Studio Code de geïntegreerde terminal.

  2. Voer de volgende git fetch en git checkout opdrachten uit om een vertakking met de naam failed-test uit de Microsoft-opslagplaats te downloaden en over te schakelen naar die vertakking:

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

    We hebben de vertakking failed-test genoemd voor leerdoeleinden. In de praktijk noemt u een vertakking na het doel of de functie.

  3. Voer deze opdrachten uit om een manifestbestand voor het lokale hulpprogramma te maken, het ReportGenerator hulpprogramma te installeren en het coverlet.msbuild pakket toe te voegen aan uw testproject:

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

    U hebt deze stap nodig omdat de failed-test vertakking niet het werk bevat dat u aan de unit-tests vertakking hebt toegevoegd.

  4. Voeg het testprojectbestand en het manifestbestand van het hulpprogramma toe aan de faseringsindex en voer uw wijzigingen door.

    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. Voer de volgende git push opdracht uit om de failed-test vertakking te uploaden naar uw GitHub-opslagplaats:

    git push origin failed-test
    

Bekijk de testfout in de pijplijn

Stel dat u haast hebt en uw werk hebt gepusht zonder de tests een laatste keer uit te voeren. Gelukkig kan de pijplijn u helpen om problemen vroeg te ondervangen wanneer er eenheidstests zijn. Dat zie je hier.

  1. Traceer in Azure Pipelines de build terwijl deze wordt uitgevoerd via de pijplijn.

  2. Vouw de eenheidstests uitvoeren uit: releasetaak terwijl deze wordt uitgevoerd.

    U ziet dat de ReturnRequestedCount testmethode mislukt.

    A screenshot of Azure Pipelines dashboard showing output log of an assertion failure on the unit test, expecting 10 but was 9.

    De test wordt doorgegeven wanneer de invoerwaarde 0 is, maar mislukt wanneer de invoerwaarde 1 of 10 is.

    De build wordt alleen naar de pijplijn gepubliceerd wanneer de vorige taak slaagt. Hier is de build niet gepubliceerd omdat de eenheidstests zijn mislukt. Dit voorkomt dat anderen per ongeluk een verbroken build kunnen verkrijgen.

In de praktijk kunt u de build niet altijd handmatig traceren terwijl deze wordt uitgevoerd. Hier volgen enkele manieren waarop u de fout kunt detecteren:

  • Een e-mailmelding van Azure DevOps

    U kunt Azure DevOps configureren om u een e-mailmelding te sturen wanneer de build is voltooid. De onderwerpregel begint met '[Build failed]' wanneer de build mislukt.

    A screenshot of a portion of a build failed email notification.

  • Azure-testplannen

    Selecteer In Azure DevOps testplannen en selecteer vervolgens Runs. U ziet de recente testuitvoeringen, inclusief de test die zojuist is uitgevoerd. Selecteer de meest recente voltooide test. U ziet dat twee van de acht tests zijn mislukt.

    A screenshot of Azure DevOps test run outcome showing two of eight failed tests as a ring chart.

  • Het dashboard

    Selecteer Overzicht in Azure DevOps en selecteer vervolgens Dashboards. U ziet dat de fout wordt weergegeven in de widget Trend van testresultaten. De widget Codedekking is leeg, wat aangeeft dat de codedekking niet is uitgevoerd.

    A screenshot of Azure DevOps dashboard trend chart widget showing two failed test in the last test run.

  • De buildbadge

    Hoewel de failed-test vertakking de buildbadge niet in het README.md-bestand bevat, ziet u dit op GitHub wanneer de build mislukt:

    A screenshot of Azure Pipelines build badge on GitHub indicating a failure.

De testfout analyseren

Wanneer eenheidstests mislukken, hebt u gewoonlijk twee keuzes, afhankelijk van de aard van de fout:

  • Als in de test een defect in de code wordt weergegeven, herstelt u de code en voert u de tests opnieuw uit.
  • Als de functionaliteit verandert, past u de test aan zodat deze overeenkomt met de nieuwe vereisten.

De fout lokaal reproduceren

In deze sectie reproduceert u de fout lokaal.

  1. Open in Visual Studio Code de geïntegreerde terminal.

  2. Voer in de terminal deze dotnet build opdracht uit om de toepassing te bouwen:

    dotnet build --configuration Release
    
  3. Voer in de terminal deze dotnet test opdracht uit om de eenheidstests uit te voeren:

    dotnet test --no-build --configuration Release
    

    U ziet dezelfde fouten die u in de pijplijn hebt gezien. Dit maakt deel uit van de uitvoer:

    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
    

De oorzaak van de fout zoeken

U ziet dat elke mislukte test een resultaat produceert dat met één is uitgeschakeld. Wanneer bijvoorbeeld 10 wordt verwacht, retourneert de test 9.

Bekijk de broncode voor de methode die wordt getest. LocalDocumentDBRepository<T>.GetItemsAsync U ziet dit als volgt:

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 dit scenario kunt u GitHub controleren om te zien of het bestand onlangs is gewijzigd.

A screenshot of GitHub showing a file diff where a minus one operation was added.

U vermoedt dat pageSize - 1 er één minder resultaat wordt geretourneerd en dat dit gewoon pageSizemoet zijn. In ons scenario is dit een fout die u hebt gemaakt tijdens het pushen van werk zonder testen, maar in een praktijkscenario kunt u contact opnemen met de ontwikkelaar die het bestand op GitHub heeft gewijzigd om de reden voor de wijziging te bepalen.

Fooi

Discussie en samenwerking kunnen ook plaatsvinden op GitHub. U kunt opmerkingen maken over een pull-aanvraag of een probleem openen.

De fout oplossen

In deze sectie lost u de fout op door de code weer in de oorspronkelijke staat te wijzigen en de tests uit te voeren om de oplossing te controleren.

  1. Open Tailspin.SpaceGame.Web/LocalDocumentDBRepository.cs vanuit de verkenner in Visual Studio Code.

  2. Wijzig de GetItemsAsync methode zoals hier wordt weergegeven:

    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);
    }
    

    Deze versie wordt gewijzigd pageSize - 1 in pageSize.

  3. Sla het bestand op.

  4. Bouw de toepassing in de geïntegreerde terminal.

    dotnet build --configuration Release
    

    U ziet dat de build slaagt.

    In de praktijk kunt u de app uitvoeren en deze kort uitproberen. Voor leerdoeleinden slaan we dat voorlopig over.

  5. Voer in de terminal de eenheidstests uit.

    dotnet test --no-build --configuration Release
    

    U ziet dat de tests zijn geslaagd.

    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. Voeg in de geïntegreerde terminal elk gewijzigd bestand toe aan de index, voer de wijzigingen door en push de vertakking naar GitHub.

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

    Fooi

    De punt (.) in dit git add voorbeeld is een jokerteken. Het komt overeen met alle niet-voorbereide bestanden in de huidige map en alle submappen.

    Voordat u dit jokerteken gebruikt, is het raadzaam om uit te voeren git status voordat u doorvoert om ervoor te zorgen dat u de bestanden die u wilt faseren.

  7. Ga terug naar Azure Pipelines. Bekijk de wijziging door de pijplijn. De tests slagen en de algehele build slaagt.

    Als u de testresultaten wilt controleren, kunt u desgewenst de tabbladen Tests en Codedekking selecteren wanneer de build is voltooid.

    U kunt ook het dashboard bekijken om de bijgewerkte resultatentrend weer te geven.

    A screenshot of Azure DevOps dashboard trend chart widget showing a return to all tests passing.

Mooi! U hebt de build opgelost. Vervolgens leert u hoe u uw Azure DevOps-omgeving opschoont.