Ćwiczenie — wykonywanie testów pokrycia kodu

Ukończone

Podobnie jak narzędzie używane do testowania jednostkowego, narzędzie używane do pokrycia kodu zależy od języka programowania i platformy aplikacji.

Jeśli aplikacja platformy .NET ma być uruchamiana w systemie Linux, coverlet jest popularną opcją. Coverlet to międzyplatformowa biblioteka pokrycia kodu dla platformy .NET.

W jaki sposób pokrycie kodu odbywa się na platformie .NET?

Sposób zbierania pokrycia kodu zależy od używanego języka programowania i platform oraz dostępnych narzędzi pokrycia kodu.

W naszym scenariuszu tailspin widzimy, że:

  • Program Visual Studio w systemie Windows umożliwia wykonywanie pokrycia kodu.

  • Jednak ponieważ kompilujemy w systemie Linux, możemy użyć coverletu , międzyplatformowej biblioteki pokrycia kodu dla platformy .NET.

    Projekt testu jednostkowego wymaga pakietu NuGet coverlet.msbuild .

  • Wyniki pokrycia kodu są zapisywane w pliku XML, aby można je było przetworzyć za pomocą innego narzędzia. Usługa Azure Pipelines obsługuje formaty wyników pokrycia Cobertura i JaCoCo.

    W tym module używamy narzędzia Cobertura.

  • Aby przekonwertować wyniki pokrycia Cobertura na format czytelny dla człowieka, możemy użyć narzędzia o nazwie ReportGenerator.

  • Narzędzie ReportGenerator udostępnia wiele formatów, w tym HTML. Formaty HTML tworzą szczegółowe raporty dla każdej klasy w projekcie platformy .NET.

    W szczególności istnieje format HTML o nazwie HtmlInline_AzurePipelines, który zapewnia wygląd zgodny z usługą Azure Pipelines.

Jak mogę zarządzać narzędziami platformy .NET?

Narzędzie .NET, takie jak ReportGenerator to specjalny pakiet NuGet, który zawiera aplikację konsolową. Narzędzie platformy .NET można zarządzać jako narzędzie globalne lub jako narzędzie lokalne.

Narzędzie globalne jest instalowane w centralnej lokalizacji i może być wywoływane z dowolnego katalogu. Jedna wersja narzędzia globalnego jest używana dla wszystkich katalogów na maszynie.

Narzędzie lokalne to bardziej izolowana kopia narzędzia platformy .NET, która jest ograniczona do określonego katalogu. Zakres umożliwia różnym katalogom zawierać różne wersje tego samego narzędzia.

Plik manifestu służy do zarządzania lokalnymi narzędziami dla danego katalogu. Ten plik jest w formacie JSON i zazwyczaj nosi nazwę dotnet-tools.json. Plik manifestu umożliwia opisanie określonych wersji narzędzi, które należy skompilować lub uruchomić aplikację.

Po dołączeniu pliku manifestu do kontroli źródła i źródeł aplikacji deweloperzy i systemy kompilacji mogą uruchomić dotnet tool restore polecenie , aby zainstalować wszystkie narzędzia wymienione w pliku manifestu. Jeśli potrzebujesz nowszej wersji narzędzia lokalnego, wystarczy zaktualizować wersję w pliku manifestu.

Aby zachować większą izolację elementów, będziesz pracować z lokalnymi narzędziami w tym module. Utworzysz manifest narzędzia zawierający ReportGenerator narzędzie. Zmodyfikujesz również potok kompilacji, aby zainstalować ReportGenerator narzędzie w celu przekonwertowania wyników pokrycia kodu na format czytelny dla człowieka.

Lokalne uruchamianie pokrycia kodu

Przed napisaniem dowolnego kodu potoku możesz spróbować wykonać czynności ręcznie, aby zweryfikować proces.

  1. W programie Visual Studio Code otwórz zintegrowany terminal.

  2. Uruchom następujące dotnet new polecenie, aby utworzyć lokalny plik manifestu narzędzia.

    dotnet new tool-manifest
    

    Polecenie tworzy plik o nazwie .config/dotnet-tools.json.

  3. Uruchom następujące dotnet tool install polecenie, aby zainstalować narzędzie ReportGenerator:

    dotnet tool install dotnet-reportgenerator-globaltool
    

    To polecenie instaluje najnowszą wersję programu ReportGenerator i dodaje wpis do pliku manifestu narzędzia.

  4. Uruchom następujące dotnet add package polecenie, aby dodać coverlet.msbuild pakiet do projektu Tailspin.SpaceGame.Web.Tests :

    dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
    
  5. Uruchom następujące dotnet test polecenie, aby uruchomić testy jednostkowe i zebrać pokrycie kodu:

    Uwaga

    Jeśli używasz terminalu programu PowerShell w programie Visual Studio, znak kontynuacji wiersza jest znakiem odwrotnym (`), więc użyj tego znaku zamiast znaku ukośnika odwrotnego (\) dla poleceń wielowierszowych.

    dotnet test --no-build \
      --configuration Release \
      /p:CollectCoverage=true \
      /p:CoverletOutputFormat=cobertura \
      /p:CoverletOutput=./TestResults/Coverage/
    

    Jeśli polecenie zakończy się niepowodzeniem, spróbuj uruchomić polecenie w następujący sposób:

    MSYS2_ARG_CONV_EXCL="*" dotnet test --no-build \
      --configuration Release \
      /p:CollectCoverage=true \
      /p:CoverletOutputFormat=cobertura \
      /p:CoverletOutput=./TestResults/Coverage/
    

    To polecenie przypomina uruchomioną wcześniej. Flagi /p: informują coverlet, który format pokrycia kodu ma być używany i gdzie umieścić wyniki.

  6. Uruchom następujące dotnet tool run polecenie, aby użyć ReportGenerator polecenia , aby przekonwertować plik Cobertura na html:

    dotnet tool run reportgenerator \
      -reports:./Tailspin.SpaceGame.Web.Tests/TestResults/Coverage/coverage.cobertura.xml \
      -targetdir:./CodeCoverage \
      -reporttypes:HtmlInline_AzurePipelines
    

    Wiele plików HTML zostanie wyświetlonych w folderze CodeCoverage w katalogu głównym projektu.

  7. W programie Visual Studio Code rozwiń folder CodeCoverage, kliknij prawym przyciskiem myszy pozycję index.htm, a następnie wybierz polecenie Ujawnij w Eksplorator plików (Odsłaniaj w programie Finder w systemie macOS lub Otwórz folder zawierający w systemie Linux).

  8. W Eksploratorze Windows (Finder w systemie macOS) kliknij dwukrotnie plik index.htm , aby otworzyć go w przeglądarce internetowej.

    Zobaczysz podsumowanie raportu pokrycia.

    A screenshot of the local code coverage report summary showing 7.7 percent line coverage.

  9. Przewiń do dołu strony, aby wyświetlić podział pokrycia według typu klasy.

    A screenshot of local coverage report class summary showing coverage stats across classes found in the Tailspin.SpaceGame.Web code.

  10. Wybierz link, aby wyświetlić TailSpin.SpaceGame.Web.LocalDocumentDBRepository<T> dalsze szczegóły.

    Zwróć uwagę, że GetItemsAsync metoda jest objęta testami jednostkowym, ale CountItemsAsync metoda nie ma pokrycia.

    A screenshot of local class coverage detail with a visual representation of unit test coverage for two C# methods, one with all code lines green (covered) and one with all lines red (not covered).

    Ma to sens, ponieważ metoda testowa FetchOnlyRequestedGameRegion wywołuje metodę GetItemsAsync , ale nie wywołuje CountItemsAsync metody . (Aby przejrzeć kod testowy, przyjrzyj się plik DocumentDBRepository_GetItemsAsyncShould.cs ).

Tworzenie gałęzi

Teraz, gdy możesz utworzyć raport pokrycia kodu lokalnie, możesz przystąpić do dodawania zadań do potoku kompilacji, który wykonuje te same zadania.

W tej sekcji utworzysz gałąź o nazwie code-coverage, w oparciu unit-tests o gałąź do przechowywania pracy. W praktyce zwykle należy utworzyć tę gałąź z main gałęzi .

  1. W programie Visual Studio Code otwórz zintegrowany terminal.

  2. W terminalu uruchom następujące git checkout polecenie, aby utworzyć gałąź o nazwie code-coverage:

    git checkout -B code-coverage
    

Dodawanie zadań kompilacji

W tej sekcji dodasz zadania, które mierzą pokrycie kodu do potoku kompilacji.

  1. W programie Visual Studio Code zmodyfikuj plik azure-pipelines.yml w następujący sposób:

    trigger:
    - '*'
    
    pool:
      vmImage: 'ubuntu-20.04'
      demands:
      - npm
    
    variables:
      buildConfiguration: 'Release'
      wwwrootDir: 'Tailspin.SpaceGame.Web/wwwroot'
      dotnetSdkVersion: '6.x'
    
    steps:
    - task: UseDotNet@2
      displayName: 'Use .NET SDK $(dotnetSdkVersion)'
      inputs:
        version: '$(dotnetSdkVersion)'
    
    - task: Npm@1
      displayName: 'Run npm install'
      inputs:
        verbose: false
    
    - script: './node_modules/.bin/node-sass $(wwwrootDir) --output $(wwwrootDir)'
      displayName: 'Compile Sass assets'
    
    - task: gulp@1
      displayName: 'Run gulp tasks'
    
    - script: 'echo "$(Build.DefinitionName), $(Build.BuildId), $(Build.BuildNumber)" > buildinfo.txt'
      displayName: 'Write build info'
      workingDirectory: $(wwwrootDir)
    
    - task: DotNetCoreCLI@2
      displayName: 'Restore project dependencies'
      inputs:
        command: 'restore'
        projects: '**/*.csproj'
    
    - task: DotNetCoreCLI@2
      displayName: 'Build the project - $(buildConfiguration)'
      inputs:
        command: 'build'
        arguments: '--no-restore --configuration $(buildConfiguration)'
        projects: '**/*.csproj'
    
    - task: DotNetCoreCLI@2
      displayName: 'Install .NET tools from local manifest'
      inputs:
        command: custom
        custom: tool
        arguments: 'restore'
    
    - task: DotNetCoreCLI@2
      displayName: 'Run unit tests - $(buildConfiguration)'
      inputs:
        command: 'test'
        arguments: '--no-build --configuration $(buildConfiguration) /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:CoverletOutput=$(Build.SourcesDirectory)/TestResults/Coverage/'
        publishTestResults: true
        projects: '**/*.Tests.csproj'
    
    - task: DotNetCoreCLI@2
      displayName: 'Create code coverage report'
      inputs:
        command: custom
        custom: tool
        arguments: 'run reportgenerator -reports:$(Build.SourcesDirectory)/**/coverage.cobertura.xml -targetdir:$(Build.SourcesDirectory)/CodeCoverage -reporttypes:HtmlInline_AzurePipelines'
    
    - task: PublishCodeCoverageResults@1
      displayName: 'Publish code coverage report'
      inputs:
        codeCoverageTool: 'cobertura'
        summaryFileLocation: '$(Build.SourcesDirectory)/**/coverage.cobertura.xml'
    
    - task: DotNetCoreCLI@2
      displayName: 'Publish the project - $(buildConfiguration)'
      inputs:
        command: 'publish'
        projects: '**/*.csproj'
        publishWebProjects: false
        arguments: '--no-build --configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/$(buildConfiguration)'
        zipAfterPublish: true
    
    - task: PublishBuildArtifacts@1
      displayName: 'Publish Artifact: drop'
      condition: succeeded()
    

    Ta wersja opiera się na istniejącej konfiguracji. Oto podsumowanie nowości:

    Zadanie usługi Azure Pipelines Display name Opis
    DotNetCoreCLI@2 Instalowanie narzędzi platformy .NET z manifestu lokalnego Instaluje narzędzia wymienione w pliku manifestu dotnet-tools.json
    DotNetCoreCLI@2 Uruchamianie testów jednostkowych — $(buildConfiguration) Uruchamia testy jednostkowe, a także zbiera pokrycie kodu w formacie Cobertura
    DotNetCoreCLI@2 Tworzenie raportu pokrycia kodu Konwertuje dane wyjściowe Cobertura na HTML
    PublishCodeCoverageResults@1 Publikowanie raportu pokrycia kodu Publikuje raport w potoku

Zatwierdź zmiany i wypchnij gałąź do usługi GitHub

W tym miejscu wypchniesz zmiany do usługi GitHub i zobaczysz przebieg potoku. Pamiętaj, że jesteś obecnie w code-coverage gałęzi .

Mimo że nie jest to wymagane, należy dodać i zatwierdzić każdy plik oddzielnie, aby każda zmiana skojarzyła się z opisowym komunikatem zatwierdzenia.

  1. W programie Visual Studio Code przejdź do terminalu.

  2. Dodaj i zatwierdź plik Tailspin.SpaceGame.Web.Tests.csproj , który zawiera teraz odwołanie do coverlet.msbuild pakietu:

    git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj
    git commit -m "Add coverlet.msbuild package"
    
  3. Dodaj i zatwierdź plik manifestu narzędzia dotnet-tools.json:

    git add .config/dotnet-tools.json
    git commit -m "Add code coverage"
    
  4. Dodaj i zatwierdź plik azure-pipelines.yml, który zawiera zaktualizowaną konfigurację kompilacji:

    git add azure-pipelines.yml
    git commit -m "Add code coverage"
    
  5. code-coverage Wypchnij gałąź do usługi GitHub.

    git push origin code-coverage
    

Obejrzyj, jak usługa Azure Pipelines uruchamia testy

W tym miejscu zobaczysz przebieg testów w potoku, a następnie zwizualizujesz wyniki z planów testów platformy Azure.

  1. W usłudze Azure Pipelines prześledzić kompilację za pomocą każdego z kroków.

  2. Po zakończeniu kompilacji wróć do strony Podsumowanie i wybierz kartę Pokrycie kodu.

    Wyświetlane są te same wyniki, które wykonaliśmy podczas uruchamiania testów lokalnie.

    A screenshot of Azure Pipelines showing the Code Coverage tab, with code coverage report summary showing 7.7 percent line coverage.

    Opcjonalnie możesz eksplorować wyniki z usługi Azure Pipelines.

Dodawanie widżetu pulpitu nawigacyjnego

W poprzedniej sekcji dodano widżet Trend wyników testów do pulpitu nawigacyjnego, co pozwala innym osobom szybko przeglądać trendy wyników testów w czasie.

W tym miejscu dodasz drugi widżet, który podsumowuje pokrycie kodu.

  1. Na nowej karcie przeglądarki przejdź do marketplace.visualstudio.com.

  2. Na karcie Azure DevOps wyszukaj pokrycie kodu.

  3. Wybierz pozycję Widżety pokrycia kodu (opublikowane przez Shane Davis).

  4. Wybierz pozycję Pobierz bezpłatnie.

  5. Z listy rozwijanej wybierz organizację usługi Azure DevOps.

  6. Wybierz Zainstaluj.

  7. Wróć do usługi Azure DevOps.

  8. Przejdź do pozycji Przegląd>Pulpity nawigacyjne.

  9. Zaznacz Edytuj.

  10. Wyszukaj pozycję Pokrycie kodu, a następnie wybierz pozycję Pokrycie kodu.

    A screenshot of Visual Studio Marketplace showing the Code Coverage widget card.

  11. Przeciągnij pole Pokrycie kodu na kanwę.

  12. Wybierz ikonę Koła zębatego , aby skonfigurować widżet.

  13. Zachowaj wszystkie ustawienia domyślne, z wyjątkiem:

    • Szerokość: wprowadź wartość 2
    • Definicja kompilacji: wybierz potok
    • Pomiar pokrycia: wybierz pozycję Linie
  14. Wybierz pozycję Zapisz.

  15. Wybierz pozycję Zakończono edytowanie.

    Widżet przedstawia procent kodu, który obejmuje testy jednostkowe.

    A screenshot of Azure DevOps Code Coverage widget showing 8 percent coverage of the sample project.

Teraz masz skonfigurowane pokrycie kodu w potoku. Mimo że istniejące pokrycie kodu jest niskie, masz punkt odniesienia, który można poprawić w czasie.

Później można skonfigurować coverlet, aby sprawdzić, czy testy zapewniają minimalny próg pokrycia. Próg może wynosić 30 procent, 50 procent lub 80 procent pokrycia, w zależności od wymagań. Kompilacja zakończy się niepowodzeniem, jeśli testy obejmują mniej niż ta kwota.

Usuwanie plików pokrycia kodu

Pamiętaj, że po uruchomieniu Reportgenerator wcześniej wiele plików HTML pojawiło się w folderze CodeCoverage w katalogu głównym projektu.

Te pliki HTML nie mają być uwzględniane w kontroli źródła i nie są już potrzebne. Mimo że plik gitignore projektu jest już skonfigurowany tak, aby ignorował wszystkie elementy w katalogu CodeCoverage, dobrym pomysłem jest usunięcie tych plików, aby nie zostały dodane do repozytorium Git w przyszłych modułach.

W programie Visual Studio Code przejdź do okna terminalu, a następnie w katalogu głównym projektu uruchom następujące polecenie:

rm -rf CodeCoverage/