Ćwiczenie — naprawianie testu, który zakończył się niepowodzeniem
W tym momencie masz sposób uruchamiania testów jednostkowych w miarę przechodzenia zmian przez potok kompilacji. Istnieje również sposób mierzenia ilości kodu objętego testami.
Zawsze dobrym pomysłem jest uruchamianie testów lokalnie przed przesłaniem zmian do potoku. Ale co się stanie, gdy ktoś zapomni i prześle zmianę, która łamie kompilację?
W tej lekcji naprawisz uszkodzoną kompilację, która jest spowodowana niepowodzeniem testu jednostkowego. Tutaj wykonasz następujące zadania:
- Pobierz kod początkowy z usługi GitHub.
- Dodaj narzędzia pokrycia kodu do projektu.
- Wypchnij kod do repozytorium.
- Obserwuj automatyczne uruchomienie potoku i testy jednostkowe kończą się niepowodzeniem.
- Odtwórz błąd lokalnie.
- Analizowanie i naprawianie błędu.
- Wypchnij poprawkę i obserwuj powodzenie kompilacji.
Przeglądanie nowego testu jednostkowego
Najnowsza funkcja zespołu obejmuje ranking. Musimy uzyskać liczbę wyników z bazy danych, aby można było napisać test jednostkowy w celu zweryfikowania IDocumentDBRepository<T>.GetItemsAsync
metody.
Oto jak wygląda test. Nie musisz jeszcze dodawać żadnego kodu.
[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();
}
Pamiętaj, TestCase
że w teście NUnit dane wbudowane są używane do testowania tej metody. NUnit wywołuje metodę testu jednostkowego ReturnRequestedCount
w następujący sposób:
ReturnRequestedCount(0);
ReturnRequestedCount(1);
ReturnRequestedCount(10);
Ten test używa ExpectedResult
również właściwości , aby uprościć kod testowy i pomóc w wyczyszczeniu intencji. NUnit automatycznie porównuje wartość zwracaną z wartością tej właściwości, usuwając konieczność jawnego wywołania asercji.
Wybierzemy kilka wartości reprezentujących typowe zapytania. Uwzględnimy również 0, aby pokryć ten przypadek krawędzi.
Pobieranie gałęzi z repozytorium GitHub
Tak jak wcześniej, pobierz failed-test
gałąź z usługi GitHub i wyewidencjonuj (lub przełącz się do) tej gałęzi.
W programie Visual Studio Code otwórz zintegrowany terminal.
Uruchom następujące
git fetch
polecenia igit checkout
, aby pobrać gałąź o nazwiefailed-test
z repozytorium Firmy Microsoft i przełączyć się do tej gałęzi:git fetch upstream failed-test git checkout -B failed-test upstream/failed-test
Nazwaliśmy gałąź
failed-test
do celów szkoleniowych. W praktyce należy nazwać gałąź po jej celu lub funkcji.Uruchom następujące polecenia, aby utworzyć lokalny plik manifestu narzędzia, zainstalować
ReportGenerator
narzędzie i dodaćcoverlet.msbuild
pakiet do projektu testów:dotnet new tool-manifest dotnet tool install dotnet-reportgenerator-globaltool dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
Ten krok jest potrzebny, ponieważ
failed-test
gałąź nie zawiera pracy dodanej dounit-tests
gałęzi.Dodaj plik projektu testowego i plik manifestu narzędzia do indeksu przejściowego i zatwierdź zmiany.
git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj git add .config/dotnet-tools.json git commit -m "Configure code coverage tests"
Uruchom następujące
git push
polecenie, aby przekazaćfailed-test
gałąź do repozytorium GitHub:git push origin failed-test
Zobacz błąd testu w potoku
Załóżmy, że spieszyłeś się i wypchnął swoją pracę bez przeprowadzania testów po raz ostatni. Na szczęście potok może pomóc w przechwytywaniu problemów na wczesnym etapie, gdy istnieją testy jednostkowe. Widać to tutaj.
W usłudze Azure Pipelines śledź kompilację, gdy jest ona uruchamiana przez potok.
Rozwiń zadanie Uruchom testy jednostkowe — wydanie , gdy jest uruchamiane.
Zobaczysz, że metoda testowa kończy się niepowodzeniem
ReturnRequestedCount
.Test kończy się powodzeniem, gdy wartość wejściowa wynosi 0, ale kończy się niepowodzeniem, gdy wartość wejściowa to 1 lub 10.
Kompilacja jest publikowana w potoku tylko wtedy, gdy poprzednie zadanie zakończy się pomyślnie. W tym miejscu kompilacja nie została opublikowana, ponieważ testy jednostkowe nie powiodły się. Zapobiega to przypadkowemu uzyskaniu uszkodzonej kompilacji przez inne osoby.
W praktyce nie zawsze będzie można ręcznie śledzić kompilację podczas jej uruchamiania. Oto kilka sposobów wykrycia błędu:
Powiadomienie e-mail z usługi Azure DevOps
Możesz skonfigurować usługę Azure DevOps, aby wysłać powiadomienie e-mail po zakończeniu kompilacji. Wiersz tematu rozpoczyna się od ciągu "[Kompilacja nie powiodła się]", gdy kompilacja zakończy się niepowodzeniem.
Plany testów platformy Azure
W usłudze Azure DevOps wybierz pozycję Plany testów, a następnie wybierz pozycję Uruchomienia. Zobaczysz ostatnie przebiegi testów, w tym te, które właśnie uruchomiono. Wybierz najnowszy ukończony test. Zobaczysz, że dwa z ośmiu testów zakończyły się niepowodzeniem.
Pulpit nawigacyjny
W usłudze Azure DevOps wybierz pozycję Przegląd, a następnie wybierz pozycję Pulpity nawigacyjne. Zostanie wyświetlony błąd w widżecie Trend wyników testów. Widżet Pokrycie kodu jest pusty, co oznacza, że pokrycie kodu nie zostało uruchomione.
Znaczek kompilacji
failed-test
Mimo że gałąź nie zawiera wskaźnika kompilacji w pliku README.md, oto co można zobaczyć w usłudze GitHub, gdy kompilacja zakończy się niepowodzeniem:
Analizowanie niepowodzenia testu
Gdy testy jednostkowe kończą się niepowodzeniem, zwykle masz dwie opcje, w zależności od charakteru błędu:
- Jeśli test ujawni usterkę w kodzie, napraw kod i uruchom ponownie testy.
- Jeśli funkcjonalność ulegnie zmianie, dostosuj test, aby był zgodny z nowymi wymaganiami.
Odtwórz błąd lokalnie
W tej sekcji odtworzysz błąd lokalnie.
W programie Visual Studio Code otwórz zintegrowany terminal.
W terminalu uruchom następujące
dotnet build
polecenie, aby skompilować aplikację:dotnet build --configuration Release
W terminalu uruchom następujące
dotnet test
polecenie, aby uruchomić testy jednostkowe:dotnet test --no-build --configuration Release
W potoku powinny zostać wyświetlone te same błędy, które wystąpiły w potoku. Oto część danych wyjściowych:
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
Znajdowanie przyczyny błędu
Zauważysz, że każdy test, który zakończył się niepowodzeniem, generuje wynik wyłączony przez jeden. Na przykład gdy oczekiwano wartości 10, test zwraca wartość 9.
Zapoznaj się z kodem źródłowym metody, która jest testowana, LocalDocumentDBRepository<T>.GetItemsAsync
. Powinien zostać wyświetlony następujący komunikat:
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);
}
W tym scenariuszu możesz sprawdzić usługę GitHub, aby sprawdzić, czy plik został niedawno zmieniony.
Podejrzewasz, że pageSize - 1
zwraca jeden mniej wyników i że powinno to być tylko pageSize
. W naszym scenariuszu jest to błąd, który wystąpił podczas wypychania pracy bez testowania, ale w rzeczywistym scenariuszu możesz sprawdzić u dewelopera, który zmienił plik w usłudze GitHub, aby określić przyczynę zmiany.
Napiwek
Dyskusje i współpraca mogą również odbywać się w usłudze GitHub. Możesz skomentować żądanie ściągnięcia lub otworzyć problem.
Naprawianie błędu
W tej sekcji naprawisz błąd, zmieniając kod z powrotem na jego oryginalny stan i uruchamiając testy w celu zweryfikowania poprawki.
W programie Visual Studio Code otwórz plik Tailspin.SpaceGame.Web/LocalDocumentDBRepository.cs z eksploratora plików.
Zmodyfikuj metodę
GetItemsAsync
, jak pokazano poniżej: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); }
Ta wersja zmienia się
pageSize - 1
napageSize
.Zapisz plik.
W zintegrowanym terminalu skompiluj aplikację.
dotnet build --configuration Release
Powinien zostać wyświetlony komunikat o pomyślnym zakończeniu kompilacji.
W praktyce możesz uruchomić aplikację i pokrótce wypróbować ją. W celach szkoleniowych pominiemy to na razie.
W terminalu uruchom testy jednostkowe.
dotnet test --no-build --configuration Release
Zobaczysz, że testy przechodzą pomyślnie.
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
W zintegrowanym terminalu dodaj każdy zmodyfikowany plik do indeksu, zatwierdź zmiany i wypchnij gałąź do usługi GitHub.
git add . git commit -m "Return correct number of items" git push origin failed-test
Napiwek
Kropka (
.
) w tymgit add
przykładzie jest symbolem wieloznacznymi. Pasuje do wszystkich nieprzytagowanych plików w bieżącym katalogu i wszystkich podkatalogach.Przed użyciem tego symbolu wieloznacznych dobrym rozwiązaniem jest uruchomienie
git status
przed zatwierdzeniem w celu upewnienia się, że pliki, które zamierzasz przygotować.Wróć do usługi Azure Pipelines. Obejrzyj zmianę przechodzącą przez potok. Testy kończą się powodzeniem, a ogólna kompilacja zakończy się powodzeniem.
Opcjonalnie, aby zweryfikować wyniki testu, możesz wybrać karty Testy i pokrycie kodu po zakończeniu kompilacji.
Możesz również sprawdzić pulpit nawigacyjny, aby wyświetlić zaktualizowany trend wyników.
Świetnie! Naprawiono kompilację. Następnie dowiesz się, jak wyczyścić środowisko usługi Azure DevOps.