Övning – Utföra kodtäckningstestning

Slutförd

Precis som verktyget du använder för enhetstestning beror verktyget du använder för kodtäckning på programmeringsspråket och programramverket.

När du riktar in dig på .NET-program som ska köras på Linux är coverlet ett populärt alternativ. Coverlet är ett plattformsoberoende kodtäckningsbibliotek för .NET.

Hur görs kodtäckning i .NET?

Hur du samlar in kodtäckning beror på vilket programmeringsspråk och ramverk du använder och vilka kodtäckningsverktyg som är tillgängliga.

I vårt Tailspin-scenario ser vi följande:

  • Visual Studio i Windows är ett sätt att utföra kodtäckning.

  • Men eftersom vi bygger på Linux kan vi använda coverlet, ett plattformsoberoende kodtäckningsbibliotek för .NET.

    Enhetstestprojektet kräver coverlet.msbuild NuGet-paketet.

  • Kodtäckningsresultat skrivs till en XML-fil så att de kan bearbetas av ett annat verktyg. Azure Pipelines stöder Cobertura - och JaCoCo-täckningsresultatformat .

    För den här modulen använder vi Cobertura.

  • Om du vill konvertera Cobertura-täckningsresultat till ett format som kan läsas av människor kan vi använda ett verktyg med namnet ReportGenerator.

  • ReportGenerator innehåller många format, inklusive HTML. HTML-formaten skapar detaljerade rapporter för varje klass i ett .NET-projekt.

    Mer specifikt finns det ett HTML-format som heter HtmlInline_AzurePipelines, som ger ett visuellt utseende som matchar Azure Pipelines.

Hur kan jag hantera .NET-verktyg?

Ett .NET-verktyg som ReportGenerator är ett särskilt NuGet-paket som innehåller ett konsolprogram. Du kan hantera ett .NET-verktyg som ett globalt verktyg eller som ett lokalt verktyg.

Ett globalt verktyg installeras på en central plats och kan anropas från valfri katalog. En version av ett globalt verktyg används för alla kataloger på datorn.

Ett lokalt verktyg är en mer isolerad kopia av ett .NET-verktyg som är begränsat till en specifik katalog. Omfång gör att olika kataloger kan innehålla olika versioner av samma verktyg.

Du använder en manifestfil för att hantera lokala verktyg för en viss katalog. Den här filen är i JSON-format och heter vanligtvis dotnet-tools.json. Med en manifestfil kan du beskriva de specifika verktygsversioner som du behöver för att skapa eller köra ditt program.

När du inkluderar manifestfilen i källkontrollen och dina programkällor kan utvecklare och byggsystem köra dotnet tool restore kommandot för att installera alla verktyg som anges i manifestfilen. När du behöver en nyare version av ett lokalt verktyg uppdaterar du helt enkelt versionen i manifestfilen.

För att hålla saker och ting mer isolerade arbetar du med lokala verktyg i den här modulen. Du skapar ett verktygsmanifest som innehåller verktyget ReportGenerator . Du kommer också att ändra bygg-pipelinen för att installera ReportGenerator verktyget för att konvertera kodtäckningsresultat till ett format som kan läsas av människor.

Köra kodtäckning lokalt

Innan du skriver någon pipelinekod kan du prova saker manuellt för att verifiera processen.

  1. Öppna den integrerade terminalen i Visual Studio Code.

  2. Kör följande dotnet new kommando för att skapa en lokal verktygsmanifestfil.

    dotnet new tool-manifest
    

    Kommandot skapar en fil med namnet .config/dotnet-tools.json.

  3. Kör följande dotnet tool install kommando för att installera ReportGenerator:

    dotnet tool install dotnet-reportgenerator-globaltool
    

    Det här kommandot installerar den senaste versionen av ReportGenerator och lägger till en post i verktygets manifestfil.

  4. Kör följande dotnet add package kommando för att lägga till coverlet.msbuild paketet i projektet Tailspin.SpaceGame.Web.Tests :

    dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
    
  5. Kör följande dotnet test kommando för att köra enhetstesterna och samla in kodtäckning:

    Kommentar

    Om du använder PowerShell-terminalen i Visual Studio är radfortsättningstecknet en backtick (`), så använd det tecknet i stället för omvänt snedstreck (\) för flerradskommandon.

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

    Om kommandot misslyckas kan du prova att köra det på följande sätt:

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

    Det här kommandot liknar det som du körde tidigare. Flaggorna /p: anger vilket kodtäckningsformat som ska användas och var resultatet ska placeras.

  6. Kör följande dotnet tool run kommando för att konvertera ReportGenerator Cobertura-filen till HTML:

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

    Många HTML-filer visas i mappen CodeCoverage i projektets rot.

  7. I Visual Studio Code expanderar du mappen CodeCoverage, högerklickar på index.htm och väljer sedan Reveal in Utforskaren (Reveal in Finder on macOS or Open Containing Folder on Linux).

  8. I Utforskaren (Finder på macOS) dubbelklickar du på index.htm för att öppna det i en webbläsare.

    Du ser sammanfattningen av täckningsrapport.

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

  9. Rulla längst ned på sidan för att se en täckningsuppdelning efter klasstyp.

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

  10. Välj länken för att TailSpin.SpaceGame.Web.LocalDocumentDBRepository<T> visa ytterligare information.

    Observera att GetItemsAsync metoden omfattas av enhetstester, men metoden CountItemsAsync har ingen täckning.

    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).

    Det är vettigt eftersom FetchOnlyRequestedGameRegion testmetoden anropar GetItemsAsync metoden, men inte anropar CountItemsAsync metoden. (Om du vill granska testkoden tittar du på DocumentDBRepository_GetItemsAsyncShould.cs-fil .)

Skapa en gren

Nu när du kan skapa en kodtäckningsrapport lokalt är du redo att lägga till uppgifter i bygg-pipelinen, som utför samma uppgifter.

I det här avsnittet skapar du en gren med namnet code-coverage, baserat på grenen unit-tests , för att lagra ditt arbete. I praktiken skulle du vanligtvis skapa den här grenen från grenen main .

  1. Öppna den integrerade terminalen i Visual Studio Code.

  2. I terminalen kör du följande git checkout kommando för att skapa en gren med namnet code-coverage:

    git checkout -B code-coverage
    

Lägga till bygguppgifter

I det här avsnittet lägger du till uppgifter som mäter kodtäckning i bygg-pipelinen.

  1. Ändra azure-pipelines.yml enligt följande i Visual Studio Code:

    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()
    

    Den här versionen bygger på din befintliga konfiguration. Här är en sammanfattning av vad som är nytt:

    Azure Pipelines-uppgift Display name Beskrivning
    DotNetCoreCLI@2 Installera .NET-verktyg från det lokala manifestet Installerar verktyg som anges i manifestfilen dotnet-tools.json
    DotNetCoreCLI@2 Köra enhetstester – $(buildConfiguration) Kör enhetstester och samlar även in kodtäckning i Cobertura-format
    DotNetCoreCLI@2 Skapa kodtäckningsrapport Konverterar Cobertura-utdata till HTML
    PublishCodeCoverageResults@1 Publicera kodtäckningsrapport Publicerar rapporten till pipelinen

Checka in dina ändringar och skicka grenen till GitHub

Här push-överför du ändringarna till GitHub och ser pipelinekörningen. Kom ihåg att du för närvarande är i grenen code-coverage .

Även om det inte krävs lägger du till och checkar in varje fil separat så att varje ändring associeras med ett beskrivande incheckningsmeddelande.

  1. I Visual Studio Code går du till terminalen.

  2. Lägg till och checka in filen Tailspin.SpaceGame.Web.Tests.csproj , som nu innehåller en referens till coverlet.msbuild paketet:

    git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj
    git commit -m "Add coverlet.msbuild package"
    
  3. Lägg till och checka in verktygets manifestfil, dotnet-tools.json:

    git add .config/dotnet-tools.json
    git commit -m "Add code coverage"
    
  4. Lägg till och checka in azure-pipelines.yml, som innehåller din uppdaterade byggkonfiguration:

    git add azure-pipelines.yml
    git commit -m "Add code coverage"
    
  5. Skicka grenen code-coverage till GitHub.

    git push origin code-coverage
    

Se hur Azure Pipelines kör testerna

Här visas testerna som körs i pipelinen och sedan visualisera resultaten från Azure Test Plans.

  1. I Azure Pipelines spårar du bygget genom vart och ett av stegen.

  2. När bygget är klart går du tillbaka till sidan Sammanfattning och väljer fliken Kodtäckning .

    Du visar samma resultat som du gjorde när du körde testerna lokalt.

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

    Som ett valfritt steg kan du utforska resultaten från Azure Pipelines.

Lägg till instrumentpanelswidgeten

I föregående avsnitt lade du till widgeten Trend för testresultat på instrumentpanelen, vilket gör att andra snabbt kan granska testresultattrender över tid.

Här lägger du till en andra widget som sammanfattar kodtäckningen.

  1. Gå till marketplace.visualstudio.com på en ny webbläsarflik.

  2. På fliken Azure DevOps söker du efter kodtäckning.

  3. Välj Kodtäckningswidgetar (publicerade av Shane Davis).

  4. Välj Hämta kostnadsfritt.

  5. I listrutan väljer du din Azure DevOps-organisation.

  6. Välj Installera.

  7. Gå tillbaka till Azure DevOps.

  8. Gå till Översiktsinstrumentpaneler>.

  9. Välj Redigera.

  10. Sök efter kodtäckning och välj sedan Kodtäckning.

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

  11. Dra Kodtäckning till arbetsytan.

  12. Välj kugghjulsikonen för att konfigurera widgeten.

  13. Behåll alla standardinställningar, förutom:

    • Bredd: Ange 2
    • Versionsdefinition: Välj din pipeline
    • Täckningsmätning: välj Linjer
  14. Välj Spara.

  15. Välj Klar med redigering.

    Widgeten visar procentandelen kod som enhetstesterna täcker.

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

Nu har du konfigurerat kodtäckning i din pipeline. Även om din befintliga kodtäckning är låg har du en baslinje som du kan förbättra med tiden.

Senare kan du konfigurera coverlet för att kontrollera om dina tester ger ett minsta tröskelvärde för täckning. Tröskelvärdet kan vara 30 procent, 50 procent eller 80 procent täckning, beroende på dina krav. Bygget misslyckas om dina tester täcker mindre än det här beloppet.

Ta bort kodtäckningsfiler

Kom ihåg att när du körde Reportgenerator tidigare visades många HTML-filer i mappen CodeCoverage i projektets rot.

Dessa HTML-filer är inte avsedda att ingå i källkontrollen och du behöver dem inte längre. Även om projektets .gitignore-fil redan har konfigurerats för att ignorera något i katalogen CodeCoverage, är det en bra idé att ta bort filerna så att de inte läggs till i Git-lagringsplatsen i framtida moduler.

I Visual Studio Code går du till terminalfönstret och kör sedan följande kommando i projektets rotkatalog:

rm -rf CodeCoverage/