Oefening: een mislukte test oplossen
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).
Open in Visual Studio Code de geïntegreerde terminal.
Voer de volgende
git fetch
engit checkout
opdrachten uit om een vertakking met de naamfailed-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.Voer deze opdrachten uit om een manifestbestand voor het lokale hulpprogramma te maken, het
ReportGenerator
hulpprogramma te installeren en hetcoverlet.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 deunit-tests
vertakking hebt toegevoegd.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"
Voer de volgende
git push
opdracht uit om defailed-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.
Traceer in Azure Pipelines de build terwijl deze wordt uitgevoerd via de pijplijn.
Vouw de eenheidstests uitvoeren uit: releasetaak terwijl deze wordt uitgevoerd.
U ziet dat de
ReturnRequestedCount
testmethode mislukt.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.
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.
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.
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:
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.
Open in Visual Studio Code de geïntegreerde terminal.
Voer in de terminal deze
dotnet build
opdracht uit om de toepassing te bouwen:dotnet build --configuration Release
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.
U vermoedt dat pageSize - 1
er één minder resultaat wordt geretourneerd en dat dit gewoon pageSize
moet 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.
Tip
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.
Open Tailspin.SpaceGame.Web/LocalDocumentDBRepository.cs in Visual Studio Code vanuit de verkenner.
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
inpageSize
.Sla het bestand op.
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.
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
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
Tip
De punt (
.
) in ditgit 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.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.
Mooi! U hebt de build opgelost. Vervolgens leert u hoe u uw Azure DevOps-omgeving opschoont.