Partilhar via


Usar cobertura de código para testes de unidade

Importante

Este artigo explica a criação do projeto de exemplo. Se você já tiver um projeto, poderá pular para a seção Ferramentas de cobertura de código.

Os testes de unidade ajudam a garantir a funcionalidade e fornecem um meio de verificação para os esforços de refatoração. A cobertura de código é uma medida da quantidade de código que é executada por testes de unidade - linhas, ramificações ou métodos. Por exemplo, se você tiver um aplicativo simples com apenas duas ramificações condicionais de código (ramificação a e ramificação b), um teste de unidade que verifica a ramificação condicional a relatará uma cobertura de código de filial de 50%.

Este artigo discute o uso da cobertura de código para testes de unidade com Coverlet e geração de relatórios usando ReportGenerator. Embora este artigo se concentre em C# e xUnit como a estrutura de teste, tanto o MSTest quanto o NUnit também funcionariam. Coverlet é um projeto de código aberto no GitHub que fornece uma estrutura de cobertura de código multiplataforma para C#. Coverlet faz parte da Fundação .NET. O Coverlet coleta dados de execução de teste de cobertura de cobertura, que são usados para geração de relatórios.

Além disso, este artigo detalha como usar as informações de cobertura de código coletadas de uma execução de teste do Coverlet para gerar um relatório. A geração de relatórios é possível usando outro projeto de código aberto no GitHub - ReportGenerator. O ReportGenerator converte relatórios de cobertura gerados pela Cobertura, entre muitos outros, em relatórios legíveis por humanos em vários formatos.

Este artigo é baseado no projeto de código-fonte de exemplo, disponível no navegador de exemplos.

Sistema em teste

O "sistema em teste" refere-se ao código contra o qual você está escrevendo testes de unidade, isso pode ser um objeto, serviço ou qualquer outra coisa que exponha a funcionalidade testável. Para este artigo, você criará uma biblioteca de classes que será o sistema em teste e dois projetos de teste de unidade correspondentes.

Criar uma biblioteca de classes

Em um prompt de comando em um novo diretório chamado UnitTestingCodeCoverage, crie uma nova biblioteca de classes padrão do .NET usando o dotnet new classlib comando:

dotnet new classlib -n Numbers

O trecho abaixo define uma classe simples PrimeService que fornece funcionalidade para verificar se um número é primo. Copie o trecho abaixo e substitua o conteúdo do arquivo Class1.cs que foi criado automaticamente no diretório Numbers . Renomeie o arquivo Class1.cs para PrimeService.cs.

namespace System.Numbers
{
    public class PrimeService
    {
        public bool IsPrime(int candidate)
        {
            if (candidate < 2)
            {
                return false;
            }

            for (int divisor = 2; divisor <= Math.Sqrt(candidate); ++divisor)
            {
                if (candidate % divisor == 0)
                {
                    return false;
                }
            }
            return true;
        }
    }
}

Gorjeta

Vale a pena mencionar que a biblioteca de Numbers classes foi intencionalmente adicionada System ao namespace. Isso permite System.Math que seja acessível sem uma using System; declaração de namespace. Para obter mais informações, consulte namespace (Referência C#).

Criar projetos de teste

Crie dois novos modelos xUnit Test Project (.NET Core) a partir do mesmo prompt de comando usando o dotnet new xunit comando:

dotnet new xunit -n XUnit.Coverlet.Collector
dotnet new xunit -n XUnit.Coverlet.MSBuild

Ambos os projetos de teste xUnit recém-criados precisam adicionar uma referência de projeto da biblioteca de classes Numbers . Isso é para que os projetos de teste tenham acesso ao PrimeService para testes. No prompt de comando, use o dotnet add comando:

dotnet add XUnit.Coverlet.Collector\XUnit.Coverlet.Collector.csproj reference Numbers\Numbers.csproj
dotnet add XUnit.Coverlet.MSBuild\XUnit.Coverlet.MSBuild.csproj reference Numbers\Numbers.csproj

O projeto MSBuild é nomeado apropriadamente, pois dependerá do pacote NuGet coverlet.msbuild . Adicione esta dependência de pacote executando o dotnet add package comando:

cd XUnit.Coverlet.MSBuild && dotnet add package coverlet.msbuild && cd ..

O comando anterior alterou diretórios efetivamente definindo o escopo para o projeto de teste MSBuild e, em seguida, adicionou o pacote NuGet. Quando isso foi feito, mudou de diretório, subindo um nível.

Abra ambos os arquivos UnitTest1.cs e substitua seu conteúdo pelo trecho a seguir. Renomeie os arquivos UnitTest1.cs para PrimeServiceTests.cs.

using System.Numbers;
using Xunit;

namespace XUnit.Coverlet
{
    public class PrimeServiceTests
    {
        readonly PrimeService _primeService;

        public PrimeServiceTests() => _primeService = new PrimeService();

        [Theory]
        [InlineData(-1), InlineData(0), InlineData(1)]
        public void IsPrime_ValuesLessThan2_ReturnFalse(int value) =>
            Assert.False(_primeService.IsPrime(value), $"{value} should not be prime");

        [Theory]
        [InlineData(2), InlineData(3), InlineData(5), InlineData(7)]
        public void IsPrime_PrimesLessThan10_ReturnTrue(int value) =>
            Assert.True(_primeService.IsPrime(value), $"{value} should be prime");

        [Theory]
        [InlineData(4), InlineData(6), InlineData(8), InlineData(9)]
        public void IsPrime_NonPrimesLessThan10_ReturnFalse(int value) =>
            Assert.False(_primeService.IsPrime(value), $"{value} should not be prime");
    }
}

Criar uma solução

No prompt de comando, crie uma nova solução para encapsular a biblioteca de classes e os dois projetos de teste. Usando o dotnet sln comando:

dotnet new sln -n XUnit.Coverage

Isso criará um novo nome XUnit.Coverage de arquivo de solução no diretório UnitTestingCodeCoverage . Adicione os projetos à raiz da solução.

dotnet sln XUnit.Coverage.sln add **/*.csproj --in-root

Crie a solução usando o dotnet build comando:

dotnet build

Se a compilação for bem-sucedida, você criou os três projetos, fez referência apropriada aos projetos e pacotes e atualizou o código-fonte corretamente. Parabéns!

Ferramentas de cobertura de código

Existem dois tipos de ferramentas de cobertura de código:

  • DataCollectors: DataCollectors monitoram a execução de testes e coletam informações sobre execuções de teste. Eles relatam as informações coletadas em vários formatos de saída, como XML e JSON. Para obter mais informações, consulte seu primeiro DataCollector.
  • Geradores de relatórios: use dados coletados de execuções de teste para gerar relatórios, geralmente como HTML estilizado.

Nesta seção, o foco está nas ferramentas de coletor de dados.

O .NET inclui um coletor de dados de cobertura de código interno, que também está disponível no Visual Studio. Esse coletor de dados gera um arquivo binário .coverage que pode ser usado para gerar relatórios no Visual Studio. O arquivo binário não é legível por humanos e deve ser convertido em um formato legível por humanos antes de poder ser usado para gerar relatórios fora do Visual Studio.

Gorjeta

A dotnet-coverage ferramenta é uma ferramenta multiplataforma que pode ser usada para converter o arquivo de resultados de teste de cobertura binária para um formato legível por humanos. Para obter mais informações, consulte dotnet-coverage.

Coverlet é uma alternativa de código aberto para o coletor embutido. Ele gera resultados de teste como arquivos Cobertura XML legíveis por humanos, que podem ser usados para gerar relatórios HTML. Para usar o Coverlet para cobertura de código, um projeto de teste de unidade existente deve ter as dependências de pacote apropriadas ou, alternativamente, confiar nas ferramentas globais do .NET e no pacote NuGet coverlet.console correspondente.

Integração com o teste .NET

O modelo de projeto de teste xUnit já se integra com coverlet.collector por padrão. No prompt de comando, altere os diretórios para o projeto XUnit.Coverlet.Collector e execute o dotnet test comando:

cd XUnit.Coverlet.Collector && dotnet test --collect:"XPlat Code Coverage"

Nota

O "XPlat Code Coverage" argumento é um nome amigável que corresponde aos coletores de dados da Coverlet. Esse nome é obrigatório, mas não diferencia maiúsculas de minúsculas. Para usar o . Coletor de dados de cobertura de código integrado da NET, use "Code Coverage".

Como parte da dotnet test execução, um arquivo coverage.cobertura.xml resultante é enviado para o diretório TestResults. O arquivo XML contém os resultados. Esta é uma opção de plataforma cruzada que depende da CLI do .NET e é ótima para sistemas de compilação onde o MSBuild não está disponível.

Abaixo está o exemplo coverage.cobertura.xml arquivo.

<?xml version="1.0" encoding="utf-8"?>
<coverage line-rate="1" branch-rate="1" version="1.9" timestamp="1592248008"
          lines-covered="12" lines-valid="12" branches-covered="6" branches-valid="6">
  <sources>
    <source>C:\</source>
  </sources>
  <packages>
    <package name="Numbers" line-rate="1" branch-rate="1" complexity="6">
      <classes>
        <class name="Numbers.PrimeService" line-rate="1" branch-rate="1" complexity="6"
               filename="Numbers\PrimeService.cs">
          <methods>
            <method name="IsPrime" signature="(System.Int32)" line-rate="1"
                    branch-rate="1" complexity="6">
              <lines>
                <line number="8" hits="11" branch="False" />
                <line number="9" hits="11" branch="True" condition-coverage="100% (2/2)">
                  <conditions>
                    <condition number="7" type="jump" coverage="100%" />
                  </conditions>
                </line>
                <line number="10" hits="3" branch="False" />
                <line number="11" hits="3" branch="False" />
                <line number="14" hits="22" branch="True" condition-coverage="100% (2/2)">
                  <conditions>
                    <condition number="57" type="jump" coverage="100%" />
                  </conditions>
                </line>
                <line number="15" hits="7" branch="False" />
                <line number="16" hits="7" branch="True" condition-coverage="100% (2/2)">
                  <conditions>
                    <condition number="27" type="jump" coverage="100%" />
                  </conditions>
                </line>
                <line number="17" hits="4" branch="False" />
                <line number="18" hits="4" branch="False" />
                <line number="20" hits="3" branch="False" />
                <line number="21" hits="4" branch="False" />
                <line number="23" hits="11" branch="False" />
              </lines>
            </method>
          </methods>
          <lines>
            <line number="8" hits="11" branch="False" />
            <line number="9" hits="11" branch="True" condition-coverage="100% (2/2)">
              <conditions>
                <condition number="7" type="jump" coverage="100%" />
              </conditions>
            </line>
            <line number="10" hits="3" branch="False" />
            <line number="11" hits="3" branch="False" />
            <line number="14" hits="22" branch="True" condition-coverage="100% (2/2)">
              <conditions>
                <condition number="57" type="jump" coverage="100%" />
              </conditions>
            </line>
            <line number="15" hits="7" branch="False" />
            <line number="16" hits="7" branch="True" condition-coverage="100% (2/2)">
              <conditions>
                <condition number="27" type="jump" coverage="100%" />
              </conditions>
            </line>
            <line number="17" hits="4" branch="False" />
            <line number="18" hits="4" branch="False" />
            <line number="20" hits="3" branch="False" />
            <line number="21" hits="4" branch="False" />
            <line number="23" hits="11" branch="False" />
          </lines>
        </class>
      </classes>
    </package>
  </packages>
</coverage>

Gorjeta

Como alternativa, você pode usar o pacote MSBuild se seu sistema de compilação já faz uso do MSBuild. No prompt de comando, altere os diretórios para o projeto XUnit.Coverlet.MSBuild e execute o dotnet test comando:

dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura

O arquivo coverage.cobertura.xml resultante é a saída. Você pode seguir o guia de integração do MSBuild aqui

Gerar relatórios

Agora que você pode coletar dados de execuções de teste de unidade, você pode gerar relatórios usando ReportGenerator. Para instalar o pacote NuGet ReportGenerator como uma ferramenta global .NET, use o dotnet tool install comando:

dotnet tool install -g dotnet-reportgenerator-globaltool

Execute a ferramenta e forneça as opções desejadas, dada a saída coverage.cobertura.xml arquivo da execução de teste anterior.

reportgenerator
-reports:"Path\To\TestProject\TestResults\{guid}\coverage.cobertura.xml"
-targetdir:"coveragereport"
-reporttypes:Html

Depois de executar esse comando, um arquivo HTML representa o relatório gerado.

Unit test-generated report

Consulte também

Passos Seguintes