Cvičení – testování pokrytí kódu

Dokončeno

Podobně jako nástroj, který používáte pro testování jednotek, závisí nástroj, který používáte pro pokrytí kódu, na programovacím jazyce a aplikační architektuře.

Když cílíte na aplikace .NET tak, aby běžely v Linuxu, je coverlet oblíbenou možností. Coverlet je multiplatformní knihovna pokrytí kódu pro .NET.

Jak se pokrytí kódu provádí v .NET?

Způsob shromažďování pokrytí kódu závisí na tom, jaký programovací jazyk a architektury používáte, a na dostupných nástrojích pokrytí kódu.

V našem scénáři Tailspin zjistíme, že:

  • Visual Studio ve Windows poskytuje způsob, jak provádět pokrytí kódu.

  • Vzhledem k tomu, že stavíme na Linuxu, můžeme použít coverlet, knihovnu pokrytí kódu pro různé platformy pro .NET.

    Projekt pro testování jednotek vyžaduje balíček NuGet obsahující coverlet.msbuild.

  • Výsledky pokrytí kódu se zapisují do souboru XML, takže je možné je zpracovávat pomocí jiného nástroje. Azure Pipelines podporuje formáty výsledků pokrytí Cobertura a JaCoCo.

    V tomto modulu používáme Cobertura.

  • K převodu výsledků pokrytí Cobertura do formátu, který je čitelný pro člověka, můžeme použít nástroj s názvem ReportGenerator.

  • ReportGenerator poskytuje mnoho formátů, včetně HTML. Formáty HTML vytvářejí podrobné sestavy pro každou třídu v projektu .NET.

    Konkrétně existuje formát HTML označovaný jako HtmlInline_AzurePipelines, který poskytuje vizuální vzhled, který odpovídá Azure Pipelines.

Jak můžu spravovat nástroje .NET?

Nástroj .NET, například ReportGenerator speciální balíček NuGet, který obsahuje konzolovou aplikaci. Nástroj .NET můžete spravovat jako globální nástroj nebo jako místní nástroj.

Globální nástroj se instaluje do centralizovaného umístění a lze volat z libovolného adresáře. Jedna verze globálního nástroje se používá pro všechny adresáře na počítači.

Místní nástroj je izolovanější kopie nástroje .NET, která je vymezená na konkrétní adresář. Obor umožňuje různým adresářům, aby obsahovaly různé verze stejného nástroje.

Soubor manifestu slouží ke správě místních nástrojů pro daný adresář. Tento soubor je ve formátu JSON a obvykle se jmenuje dotnet-tools.json. Soubor manifestu umožňuje popsat konkrétní verze nástrojů, které potřebujete k sestavení nebo spuštění aplikace.

Když do správy zdrojového kódu a zdrojů aplikací zahrnete soubor manifestu, můžou vývojáři a systémy sestavení spustit dotnet tool restore příkaz, který nainstaluje všechny nástroje uvedené v souboru manifestu. Pokud potřebujete novější verzi místního nástroje, stačí aktualizovat verzi v souboru manifestu.

Pokud chcete izolovat věci, budete v tomto modulu pracovat s místními nástroji. Vytvoříte manifest nástroje, který obsahuje ReportGenerator nástroj. Kanál buildu také upravíte tak, aby nástroj nainstaloval za účelem převodu ReportGenerator výsledků pokrytí kódu do čitelného formátu pro člověka.

Spuštění pokrytí kódu místně

Než napíšete kód kanálu, můžete proces ověřit ručně.

  1. V editoru Visual Studio Code otevřete integrovaný terminál.

  2. Spuštěním následujícího dotnet new příkazu vytvořte soubor manifestu místního nástroje.

    dotnet new tool-manifest
    

    Příkaz vytvoří soubor s názvem .config/dotnet-tools.json.

  3. Spuštěním následujícího dotnet tool install příkazu nainstalujte ReportGenerator:

    dotnet tool install dotnet-reportgenerator-globaltool
    

    Tento příkaz nainstaluje nejnovější verzi ReportGenerator souboru manifestu nástroje a přidá do souboru manifestu nástroje položku.

  4. Spuštěním následujícího dotnet add package příkazu přidejte coverlet.msbuild balíček do projektu Tailspin.SpaceGame.Web.Tests :

    dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
    
  5. Spuštěním následujícího dotnet test příkazu spusťte testy jednotek a shromážděte pokrytí kódu:

    Poznámka:

    Pokud používáte terminál PowerShellu v sadě Visual Studio, je znak pokračování řádku zpětným znaméčkem (`), takže tento znak použijte místo znaku zpětného lomítka (\) pro příkazy s více řádky.

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

    Pokud příkaz selže, zkuste ho spustit následujícím způsobem:

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

    Tento příkaz vypadá podobně jako ten, který jste spustili předtím. Příznaky /p: informují coverlet, jaký formát pokrytí kódu se má použít a kam umístit výsledky.

  6. Spuštěním následujícího dotnet tool run příkazu převeďte ReportGenerator soubor Cobertura na HTML:

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

    Mnoho souborů HTML se zobrazí ve složce CodeCoverage v kořenovém adresáři projektu.

  7. V editoru Visual Studio Code rozbalte složku CodeCoverage, klikněte pravým tlačítkem na index.htm a pak vyberte Zobrazit v Průzkumník souborů (Zobrazit ve Finderu v systému macOS nebo Otevřít složku obsahující v Linuxu).

  8. V Průzkumníku Windows (Finder v macOS) poklikáním otevřete index.htm ve webovém prohlížeči.

    Zobrazí se souhrn sestavy pokrytí.

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

  9. Posuňte se do dolní části stránky, abyste viděli rozpis pokrytí podle typu třídy.

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

  10. Výběrem odkazu TailSpin.SpaceGame.Web.LocalDocumentDBRepository<T> zobrazíte další podrobnosti.

    Všimněte si, že metoda GetItemsAsync je pokryta testy jednotek, ale metoda CountItemsAsync nemá žádné pokrytí.

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

    To dává smysl, protože FetchOnlyRequestedGameRegion testovací metoda volá metodu GetItemsAsync , ale nevolá metodu CountItemsAsync . (Pokud chcete zkontrolovat testovací kód, podívejte se na soubor DocumentDBRepository_GetItemsAsyncShould.cs .)

Vytvoření větve

Teď, když můžete sestavu pokrytí kódu sestavit místně, můžete do kanálu buildu přidat úlohy, které provádějí stejné úlohy.

V této části vytvoříte větev s názvem code-coveragena základě unit-tests větve, která bude obsahovat vaši práci. V praxi byste tuto větev obvykle vytvořili z main větve.

  1. V editoru Visual Studio Code otevřete integrovaný terminál.

  2. Spuštěním následujícího git checkout příkazu v terminálu vytvořte větev s názvem code-coverage:

    git checkout -B code-coverage
    

Přidání úloh sestavení

V této části přidáte úlohy, které měří pokrytí kódu do kanálu buildu.

  1. V editoru Visual Studio Code upravte azure-pipelines.yml následujícím způsobem:

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

    Tato verze používá jako základ stávající konfiguraci. Tady je souhrn novinek:

    Úloha v Azure Pipelines Zobrazovaný název Popis
    DotNetCoreCLI@2 Instalace nástrojů .NET z místního manifestu Nainstaluje nástroje uvedené v souboru manifestu dotnet-tools.json.
    DotNetCoreCLI@2 Run unit tests - $(buildConfiguration) (Spuštění testů jednotek – $(buildConfiguration)) Spustí testy jednotek a také shromáždí informace o pokrytí kódu ve formátu Cobertura.
    DotNetCoreCLI@2 Create code coverage report (Vytvoření sestavy pokrytí kódu) Převede výstup ve formátu Cobertura do formátu HTML.
    PublishCodeCoverageResults@1 Publish code coverage report (Publikování sestavy pokrytí kódu) Publikuje sestavu do kanálu.

Potvrzení změn a nasdílení větve do GitHubu

Tady nasdílíte změny do GitHubu a zobrazí se spuštění kanálu. Vzpomeňte si, že právě jste ve code-coverage větvi.

I když to není povinné, přidáte a potvrdíte každý soubor samostatně, aby každá změna byla přidružena k popisné zprávě potvrzení.

  1. V aplikaci Visual Studio Code přejděte do terminálu.

  2. Přidejte a potvrďte soubor Tailspin.SpaceGame.Web.Tests.csproj , který teď obsahuje odkaz na coverlet.msbuild balíček:

    git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj
    git commit -m "Add coverlet.msbuild package"
    
  3. Přidejte a potvrďte soubor manifestu nástroje dotnet-tools.json:

    git add .config/dotnet-tools.json
    git commit -m "Add code coverage"
    
  4. Přidejte a potvrďte azure-pipelines.yml, která obsahuje aktualizovanou konfiguraci sestavení:

    git add azure-pipelines.yml
    git commit -m "Add code coverage"
    
  5. Nasdílejte code-coverage větev do GitHubu.

    git push origin code-coverage
    

Sledování spouštění testů v Azure Pipelines

Tady uvidíte spuštění testů v kanálu a pak vizualizovat výsledky z azure Test Plans.

  1. V Azure Pipelines trasujte sestavení jednotlivými kroky.

  2. Po dokončení sestavení se vraťte na stránku Souhrn a vyberte kartu Pokrytí kódu.

    Zobrazí se stejné výsledky jako při místním spuštění testů.

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

    Jako volitelný krok můžete prozkoumat výsledky z Azure Pipelines.

Přidání widgetu řídicího panelu

V předchozí části jste do řídicího panelu přidali widget Trend výsledků testů, který ostatním umožňuje rychle zkontrolovat trendy výsledků testů v průběhu času.

Tady přidáte druhý widget, který shrnuje pokrytí kódu.

  1. Na nové kartě prohlížeče přejděte na marketplace.visualstudio.com.

  2. Na kartě Azure DevOps vyhledejte pokrytí kódu.

  3. Vyberte widgety pokrytí kódu (publikoval Shane Davis).

  4. Vyberte Získat zdarma.

  5. V rozevíracím seznamu vyberte svoji organizaci Azure DevOps.

  6. Vyberte volbu Instalovat.

  7. Vraťte se do Azure DevOps.

  8. Přejděte na řídicí panely přehledu>.

  9. Vyberte položku Upravit.

  10. Vyhledejte pokrytí kódu a pak vyberte Pokrytí kódu.

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

  11. Widget Code Coverage (Pokrytí kódu) přetáhněte na plátno.

  12. Výběrem ikony ozubeného kola nakonfigurujte widget.

  13. Ponechte všechna výchozí nastavení s výjimkou:

    • Šířka: Enter 2
    • Definice sestavení: Výběr kanálu
    • Měření pokrytí: vyberte Čáry.
  14. Zvolte Uložit.

  15. Vyberte Úpravy jsou hotové.

    Widget zobrazí procento kódu, který pokrývají testy jednotek.

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

Teď máte ve svém kanálu nastavené pokrytí kódu. Ačkoli je vaše stávající pokrytí kódu nízké, máte základní úroveň, kterou můžete postupně zlepšovat.

Později můžete nakonfigurovat coverlet a zkontrolovat, jestli testy poskytují minimální prahovou hodnotu pokrytí. V závislosti na vašich požadavcích může být prahová hodnota 30 procent, 50 procent nebo 80 procent pokrytí. Sestavení selže, pokud testy pokrývají méně než tuto částku.

Odebrání souborů pokrytí kódu

Vzpomeňte si, že když jste spustili Reportgenerator dříve, mnoho souborů HTML se objevilo ve složce CodeCoverage v kořenovém adresáři projektu.

Tyto soubory HTML nejsou určené k zahrnutí do správy zdrojového kódu a už je nepotřebujete. I když je soubor .gitignore projektu už nastavený tak, aby ignoroval cokoli v adresáři CodeCoverage, je vhodné tyto soubory odstranit, aby se do úložiště Git nepřidali v budoucích modulech.

V editoru Visual Studio Code přejděte do okna terminálu a potom v kořenovém adresáři projektu spusťte tento příkaz:

rm -rf CodeCoverage/