Cvičení – oprava selhání testu
V této chvíli máte možnost spouštět testy jednotek tak, jak kanálem buildu procházejí změny. Máte také způsob, jak můžete měřit množství kódu, který pokrývají vaše testy.
Vždy je vhodné spouštět testy místně před odesláním změn do kanálu. Co se ale stane, když někdo zapomene a odešle změnu, která způsobí selhání sestavení?
V této lekci opravíte poškozené sestavení, které je způsobeno neúspěšným testem jednotek. V této části provedete tyto akce:
- Získejte počáteční kód z GitHubu.
- Přidejte do projektu nástroje pro pokrytí kódu.
- Nasdílíte tento kód do vašeho úložiště.
- Budete sledovat automatické spuštění kanálu a selhání testu jednotek.
- Chybu reprodukujete místně.
- Zanalyzujete a opravíte selhání.
- Nasdílíte opravu a budete sledovat úspěšné vytvoření sestavení.
Revize nového testu jednotek
Nejnovější funkce týmu zahrnuje tabulku výsledků. Potřebujeme získat počet skóre z databáze, abychom mohli napsat test jednotek pro ověření IDocumentDBRepository<T>.GetItemsAsync
metody.
Test vypadá takto. Zatím nemusíte přidávat žádný kód.
[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();
}
Připomínáme, že v testu nástroje NUnit poskytuje vložená data k otestování této metody funkce TestCase
. NUnit volá metodu ReturnRequestedCount
pro test jednotek takto:
ReturnRequestedCount(0);
ReturnRequestedCount(1);
ReturnRequestedCount(10);
Tento test používá také vlastnost ExpectedResult
ke zjednodušení testovacího kódu a k tomu, aby byl jasný záměr testu. NUnit automaticky porovnává vrácenou hodnotu s hodnotou této vlastnosti, takže není potřeba explicitně volat kontrolní výraz.
Zvolíme několik hodnot, které představují typické dotazy. Zahrneme také 0, abychom tento hraniční případ pokryli.
Načtení větve z GitHubu
Jak jste to udělali dříve, načtěte větev z GitHubu failed-test
a podívejte se (nebo přepněte na) tuto větev.
V editoru Visual Studio Code otevřete integrovaný terminál.
Spuštěním následujících
git fetch
příkazůgit checkout
stáhněte větev pojmenovanoufailed-test
z úložiště Microsoftu a přepněte na tuto větev:git fetch upstream failed-test git checkout -B failed-test upstream/failed-test
Větev
failed-test
jsme pojmenovali pro účely výuky. V praxi byste větev pojmenovala za jejím účelem nebo funkcí.Spuštěním těchto příkazů vytvořte soubor manifestu místního nástroje, nainstalujte
ReportGenerator
nástroj a přidejtecoverlet.msbuild
balíček do projektu testů:dotnet new tool-manifest dotnet tool install dotnet-reportgenerator-globaltool dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
Tento krok potřebujete, protože
failed-test
větev neobsahuje práci, kterou jste přidali dounit-tests
větve.Přidejte soubor testovacího projektu a soubor manifestu nástroje do přípravného indexu a potvrďte změny.
git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj git add .config/dotnet-tools.json git commit -m "Configure code coverage tests"
Spuštěním následujícího
git push
příkazu nahrajtefailed-test
větev do úložiště GitHub:git push origin failed-test
Selhání testu v kanálu
Řekněme, že jste byli ve spěchu a vysadili svou práci bez toho, abyste testy spustili jednou do posledního okamžiku. Kanál vám naštěstí může pomoct zachytit problémy v rané fázi, když dojde k testům jednotek. Vidíte to tady.
V Azure Pipelines sledujte sestavení, jak prochází kanálem.
Rozbalte spuštěnou úlohu Run unit tests - Release (Spuštění testů jednotek – vydání).
Uvidíte, že testovací metoda
ReturnRequestedCount
selže.Test projde, když je vstupní hodnota 0, ale selže, když je vstupní hodnota 1 nebo 10.
Sestavení se publikuje do kanálu jen v případě, že je předchozí úloha úspěšná. Sestavení se zde nepublikovalo, protože testy jednotek selhaly. To zabrání tomu, aby ostatní dostali sestavení s chybami.
V praxi nebudete vždycky manuálně sledovat spouštění sestavení. Tady je několik způsobů, jak můžete zjistit selhání:
E-mailové oznámení z Azure DevOps
Azure DevOps můžete nakonfigurovat tak, aby vám po dokončení sestavení poslalo e-mailové oznámení. Pokud sestavení selže, začíná řádek předmětu označením „Build failed“ (Sestavení selhalo).
Azure Test Plans
V Azure DevOps vyberte Testovací plány a pak vyberte Spustit. Zobrazí se vám nedávná spuštění testů včetně toho, který právě proběhl. Vyberte nejnovější dokončený test. Vidíte, že dva z osmi testů selhaly.
Řídicí panel
V Azure DevOps vyberte Přehled a pak vyberte Řídicí panely. Ve widgetu Test Results Trend (Trend výsledků testů) se vám zobrazí selhání testu. Widget Pokrytí kódu je prázdný, což znamená, že pokrytí kódu nebylo spuštěno.
Odznáček buildu
failed-test
I když větev do souboru README.md neobsahuje odznáček buildu, uvidíte na GitHubu, když se sestavení nezdaří:
Analýza selhání testu
Pokud testy jednotek selžou, obvykle máte dvě možnosti v závislosti na povaze selhání:
- Pokud test odhalí chybu v kódu, opravte kód a znovu spusťte testy.
- Pokud se funkce změní, upravte test tak, aby odpovídal novým požadavkům.
Reprodukování selhání místně
V této části reprodukujete selhání místně.
V editoru Visual Studio Code otevřete integrovaný terminál.
V terminálu spusťte tento
dotnet build
příkaz pro sestavení aplikace:dotnet build --configuration Release
V terminálu spusťte tento
dotnet test
příkaz a spusťte testy jednotek:dotnet test --no-build --configuration Release
Měly by se zobrazit stejné chyby, které jste viděli v kanálu. Tady je část výstupu:
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
Zjištění příčiny chyby
Všimněte si, že každý neúspěšný test vytvoří výsledek, který je o jeden vypnutý. Pokud se například očekává hodnota 10, vrátí test hodnotu 9.
Podívejte se na zdrojový kód pro otestovanou LocalDocumentDBRepository<T>.GetItemsAsync
metodu . Měli byste vidět toto:
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);
}
V tomto scénáři můžete zkontrolovat GitHub a zjistit, jestli se soubor nedávno změnil.
Máte podezření, že pageSize - 1
vrací jeden méně výsledků a že by to mělo být jen pageSize
. V našem scénáři se jedná o chybu, kterou jste provedli, když jste odeslali práci bez testování, ale v reálném scénáři byste mohli zjistit příčinu změny u vývojáře, který soubor na GitHubu změnil.
Tip
V GitHubu je také možné diskutovat a spolupracovat. Můžete okomentovat žádost o přijetí změn nebo otevřít nějaký problém.
Oprava chyby
V této části chybu opravíte tak, že kód změníte zpět do původního stavu a spustíte testy a ověříte opravu.
V editoru Visual Studio Code otevřete soubor Tailspin.SpaceGame.Web/LocalDocumentDBRepository.cs z průzkumníka souborů.
Upravte metodu
GetItemsAsync
, jak je znázorněno zde: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); }
Tato verze změní
pageSize - 1
napageSize
.Soubor uložte.
V integrovaném terminálu sestavte aplikaci.
dotnet build --configuration Release
Měli byste vidět, že sestavení bude úspěšné.
V praxi můžete aplikaci spustit a krátce ji vyzkoušet. Pro účely výuky to prozatím přeskočíme.
V terminálu spusťte testy jednotek.
dotnet test --no-build --configuration Release
Uvidíte, že testy budou úspěšné.
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
V integrovaném terminálu přidejte každý upravený soubor do indexu, potvrďte změny a nasdílejte větev do GitHubu.
git add . git commit -m "Return correct number of items" git push origin failed-test
Tip
Tečka (
.
) v tomtogit add
příkladu je zástupný znak. Odpovídá všem souborům v aktuálním adresáři a všech podadresářích, které nejsou v přípravném prostředí.Před použitím tohoto zástupné znaky je vhodné spustit
git status
před potvrzením, abyste zajistili, že připravíte soubory, které chcete provést.Vraťte se do Azure Pipelines. Sledujte, jak změna prochází kanálem. Testy projdou a celkové sestavení bude úspěšné.
Pokud chcete ověřit výsledky testu, můžete po dokončení sestavení vybrat karty Testy a pokrytí kódu.
Můžete se také podívat na řídicí panel a zobrazit aktualizovaný trend výsledků.
Výborně! Opravili jste sestavení. Dále se dozvíte, jak vyčistit prostředí Azure DevOps.