Exercício – Realizar testes de cobertura do código

Concluído

Assim como a ferramenta que você usa para teste de unidade, a ferramenta que você usa para cobertura de código depende da linguagem de programação e da estrutura do aplicativo.

Quando você direciona aplicativos .NET para serem executados no Linux, o coverlet é uma opção popular. Coverlet é uma biblioteca de cobertura de código multiplataforma para .NET.

Como é feita a cobertura de código no .NET?

A maneira como você coleta a cobertura de código depende de qual linguagem de programação e estruturas você está usando e quais ferramentas de cobertura de código estão disponíveis.

Em nosso cenário Tailspin, descobrimos que:

  • O Visual Studio no Windows fornece uma forma de realizar a cobertura do código.

  • No entanto, como estamos construindo no Linux, podemos usar coverlet, uma biblioteca de cobertura de código multiplataforma para .NET.

    O projeto de teste de unidades requer o pacote NuGet coverlet.msbuild.

  • Os resultados da cobertura do código são escritos num ficheiro XML para que possam ser processados por outra ferramenta. O Azure Pipelines suporta os formatos de resultados de cobertura Cobertura e JaCoCo.

    Para este módulo, estamos usando Cobertura.

  • Para converter os resultados da cobertura do Cobertura para um formato legível por humanos, podemos usar uma ferramenta chamada ReportGenerator.

  • ReportGenerator fornece muitos formatos, incluindo HTML. Os formatos HTML criam relatórios detalhados para cada classe em um projeto .NET.

    Especificamente, há um formato HTML chamado HtmlInline_AzurePipelines, que fornece uma aparência visual que corresponde aos Pipelines do Azure.

Como posso gerenciar ferramentas .NET?

Uma ferramenta .NET, como ReportGenerator é um pacote NuGet especial que contém um aplicativo de console. Você pode gerenciar uma ferramenta .NET como uma ferramenta global ou como uma ferramenta local.

Uma ferramenta global é instalada em um local centralizado e pode ser chamada de qualquer diretório. Uma versão de uma ferramenta global é usada para todos os diretórios na máquina.

Uma ferramenta local é uma cópia mais isolada de uma ferramenta .NET com escopo para um diretório específico. O escopo permite que diretórios diferentes contenham versões diferentes da mesma ferramenta.

Você usa um arquivo de manifesto para gerenciar ferramentas locais para um determinado diretório. Esse arquivo está no formato JSON e normalmente é chamado dotnet-tools.json. Um arquivo de manifesto permite que você descreva as versões específicas da ferramenta que você precisa para criar ou executar seu aplicativo.

Quando você inclui o arquivo de manifesto no controle do código-fonte e nas fontes do aplicativo, os desenvolvedores e os sistemas de compilação podem executar o dotnet tool restore comando para instalar todas as ferramentas listadas no arquivo de manifesto. Quando você precisar de uma versão mais recente de uma ferramenta local, basta atualizar a versão no arquivo de manifesto.

Para manter as coisas mais isoladas, você trabalhará com ferramentas locais neste módulo. Você criará um manifesto da ferramenta que inclui a ReportGenerator ferramenta. Você também modificará seu pipeline de compilação para instalar a ferramenta para converter os resultados da ReportGenerator cobertura de código em um formato legível por humanos.

Executar a cobertura do código localmente

Antes de escrever qualquer código de pipeline, você pode tentar coisas manualmente para verificar o processo.

  1. No Visual Studio Code, abra o terminal integrado.

  2. Execute o seguinte dotnet new comando para criar um arquivo de manifesto da ferramenta local.

    dotnet new tool-manifest
    

    O comando cria um arquivo chamado .config/dotnet-tools.json.

  3. Execute o seguinte dotnet tool install comando para instalar o ReportGenerator:

    dotnet tool install dotnet-reportgenerator-globaltool
    

    Este comando instala a versão mais recente e adiciona uma entrada ao arquivo de ReportGenerator manifesto da ferramenta.

  4. Execute o seguinte dotnet add package comando para adicionar o coverlet.msbuild pacote ao projeto Tailspin.SpaceGame.Web.Tests :

    dotnet add Tailspin.SpaceGame.Web.Tests package coverlet.msbuild
    
  5. Execute o seguinte dotnet test comando para executar seus testes de unidade e coletar cobertura de código:

    Nota

    Se você estiver usando o terminal do PowerShell no Visual Studio, o caractere de continuação de linha será um backtick (), portanto, use esse caractere no lugar do caractere de barra invertida (`\) para comandos de várias linhas.

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

    Se o comando falhar, tente executá-lo da seguinte forma:

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

    Este comando é semelhante a um que executou anteriormente. Os sinalizadores /p: indicam ao coverlet qual formato de cobertura de código utilizar e onde colocar os resultados.

  6. Execute o seguinte dotnet tool run comando para converter ReportGenerator o arquivo Cobertura em HTML:

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

    Muitos arquivos HTML aparecerão na pasta CodeCoverage na raiz do projeto.

  7. No Visual Studio Code, expanda a pasta CodeCoverage, clique com o botão direito do mouse em index.htm e selecione Revelar no Explorador de Arquivos (Revelar no Finder no macOS ou Abrir pasta contendo no Linux).

  8. No Windows Explorer (Finder no macOS), clique duas vezes em índice.htm para abri-lo em um navegador da Web.

    Você verá o resumo do relatório de cobertura.

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

  9. Desloque-se para a parte inferior da página para ver uma discriminação da cobertura por tipo de classe.

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

  10. Selecione o link para para TailSpin.SpaceGame.Web.LocalDocumentDBRepository<T> ver mais detalhes.

    Observe que o método é coberto por testes de unidade, mas o GetItemsAsync CountItemsAsync método não tem cobertura.

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

    Isso faz sentido, porque o método de teste chama o método, mas não chama o FetchOnlyRequestedGameRegion GetItemsAsync CountItemsAsync método. (Para rever o código de teste, olhe para o DocumentDBRepository_GetItemsAsyncShould.cs arquivo.)

Criar um ramo

Agora que você pode criar um relatório de cobertura de código localmente, está pronto para adicionar tarefas ao seu pipeline de compilação, que executa as mesmas tarefas.

Nesta seção, você criará uma ramificação chamada code-coverage, com base na unit-tests ramificação, para manter seu trabalho. Na prática, você normalmente criaria esse ramo a partir do main ramo.

  1. No Visual Studio Code, abra o terminal integrado.

  2. No terminal, execute o seguinte git checkout comando para criar uma ramificação chamada code-coverage:

    git checkout -B code-coverage
    

Adicionar tarefas de compilação

Nesta seção, você adicionará tarefas que medem a cobertura de código ao seu pipeline de compilação.

  1. No Visual Studio Code, modifique azure-pipelines.yml da seguinte maneira:

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

    Esta versão baseia-se na configuração existente. Aqui está um resumo das novidades:

    Tarefa do Azure Pipelines Display name Descrição
    DotNetCoreCLI@2 Instalar ferramentas .NET a partir do manifesto local Instala ferramentas listadas no arquivo de manifesto, dotnet-tools.json
    DotNetCoreCLI@2 Run unit tests - $(buildConfiguration) Executa os testes de unidades e também recolhe a cobertura do código no formato Cobertura
    DotNetCoreCLI@2 Create code coverage report Converte o resultado de Cobertura em HTML
    PublishCodeCoverageResults@1 Publish code coverage report Publica o relatório no pipeline

Confirme suas alterações e envie a ramificação para o GitHub

Aqui você envia suas alterações para o GitHub e vê o pipeline ser executado. Lembre-se de que você está atualmente no code-coverage ramo.

Embora não seja necessário, aqui você adicionará e confirmará cada arquivo separadamente para que cada alteração seja associada a uma mensagem de confirmação descritiva.

  1. No Visual Studio Code, aceda ao terminal.

  2. Adicione e confirme o arquivo Tailspin.SpaceGame.Web.Tests.csproj , que agora contém uma referência ao coverlet.msbuild pacote:

    git add Tailspin.SpaceGame.Web.Tests/Tailspin.SpaceGame.Web.Tests.csproj
    git commit -m "Add coverlet.msbuild package"
    
  3. Adicione e confirme o arquivo de manifesto da ferramenta, dotnet-tools.json:

    git add .config/dotnet-tools.json
    git commit -m "Add code coverage"
    
  4. Adicione e confirme azure-pipelines.yml, que contém sua configuração de compilação atualizada:

    git add azure-pipelines.yml
    git commit -m "Add code coverage"
    
  5. Empurre a ramificação para o code-coverage GitHub.

    git push origin code-coverage
    

Veja o Azure Pipelines a executar os testes

Aqui, você verá os testes executados no pipeline e, em seguida, visualizará os resultados dos Planos de Teste do Azure.

  1. No Azure Pipelines, rastreie a compilação através de cada uma das etapas.

  2. Quando a compilação terminar, volte para a página Resumo e selecione a guia Cobertura de código .

    Você visualiza os mesmos resultados que fez quando executou os testes localmente.

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

    Como passo opcional, pode explorar os resultados do Azure Pipelines.

Adicionar o widget do painel

Na seção anterior, você adicionou o widget Tendência de resultados de teste ao seu painel, que permite que outras pessoas analisem rapidamente as tendências de resultados de teste ao longo do tempo.

Aqui, você adicionará um segundo widget que resume a cobertura do código.

  1. Em uma nova guia do navegador, vá para marketplace.visualstudio.com.

  2. Na guia Azure DevOps, procure cobertura de código.

  3. Selecione Widgets de cobertura de código (publicado por Shane Davis).

  4. Selecione Obter gratuitamente.

  5. Na lista suspensa, selecione sua organização do Azure DevOps.

  6. Selecione Instalar.

  7. Volte para o Azure DevOps.

  8. Vá para Painéis de visão geral>.

  9. Selecione Editar.

  10. Procure Cobertura de código e, em seguida, selecione Cobertura de código.

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

  11. Arraste Cobertura do Código para a tela.

  12. Selecione o ícone de engrenagem para configurar o widget.

  13. Mantenha todas as configurações padrão, exceto para:

    • Largura: Digite 2
    • Definição de compilação: selecione seu pipeline
    • Medição de cobertura: selecione Linhas
  14. Selecione Guardar.

  15. Selecione Edição Concluída.

    O widget mostra a percentagem de código que os seus testes de unidades abrangem.

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

Agora tem a cobertura do código configurada no pipeline. Embora a sua cobertura do código existente seja baixa, tem uma linha de base que pode melhorar ao longo do tempo.

Mais tarde, você pode configurar o coverlet para verificar se seus testes fornecem um limite mínimo de cobertura. Seu limite pode ser de 30%, 50% ou 80% de cobertura, dependendo de suas necessidades. A compilação falhará se seus testes cobrirem menos do que esse valor.

Remover ficheiros da cobertura do código

Lembre-se de que, quando você executou Reportgenerator anteriormente, muitos arquivos HTML apareceram na pasta CodeCoverage na raiz do projeto.

Esses arquivos HTML não se destinam a ser incluídos no controle do código-fonte, e você não precisa mais deles. Embora o arquivo .gitignore do projeto já esteja configurado para ignorar qualquer coisa no diretório CodeCoverage, é uma boa ideia excluir esses arquivos para que eles não sejam adicionados ao seu repositório Git em módulos futuros.

No Visual Studio Code, vá para a janela do terminal e, em seguida, no diretório raiz do projeto, execute este comando:

rm -rf CodeCoverage/