Teste de unidade com xUnit
Tags: dotnet, csharp, vscode, xunit
Published: 2021-04-21 22:00:09

Pré-requisitos: VSCode e SDK do .NET

Primeiro criaremos a estrutura de pastas para organizar separadamente o projeto do tipo **xUnit** do projeto class library que suportará a classe "Calculadora" e o método "Somar" para exemplificar o uso do framework xUnit.net.

Iremos utilizar também o **coverlet** para quantificar a cobertura de código e o **reportgenerator** para exibir a página de relatório com o percentual de cobertura.

Para criar a estrutura de pasta execute o comando:
```
mkdir exemplo-teste-unidade-xunit
```
Comando para mudar de diretório:
```
cd exemplo-teste-unidade-xunit
```
Comando para criar um novo projeto do tipo "class library" com o nome "calculadora.lib":
```
dotnet new classlib -o calculadora.lib
```
Comando para criar um novo projeto de testes com as referências inclusas da biblioteca do "xunit":
```
dotnet new xunit -o calculadora.tests
```
Comando para adicionar ao projeto de testes a referência do projeto "calculadora.lib":
```
dotnet add ./calculadora.tests/calculadora.tests.csproj reference ./calculadora.lib/calculadora.lib.csproj
```
Comando para abrir o Visual Code a partir da pasta "exemplo-teste-unidade-xunit":
```
code .
```

No projeto "calculadora.lib" crie a classe "Calculadora" com o método "Somar" recebendo dois parâmetros do tipo inteiro para realizar a soma:

```C#
    public class Calculadora
    {
        public int Soma(int primeiroNumero, int segundoNumero)
        {
            return primeiroNumero + segundoNumero;
        }
    }
```

Para criar o cenário de testes, expanda a pasta "calculadora.tests" e crie a classe "CalculadoraTestes" com os seguintes métodos com o atributo "Fact", "Theory" e "InlineData", que irei explicar em seguida.

Inclua a referência ao projeto "calculadora.lib":
```C#
using calculadora.lib;
```

```C#
 public class CalculadoraTestes
    {
        [Fact]
        public void Soma_Calculadora_RetornarValorInteiroPositivoCorreto()
        {
            //Arrange
            Calculadora calculadora = new Calculadora();
            //Act
            int resultadoSoma = calculadora.Soma(5,2);
            //Assert
            Assert.Equal(7, resultadoSoma);
        }

        [Theory]
        [InlineData(1,9)]
        [InlineData(8,2)]
        [InlineData(5,5)]
        public void Soma_Calculadora_RetornarValor10InteiroPositivo(int primeiroValor, int segundoValor)
        {
            //Arrange
            Calculadora calculadora = new Calculadora();
            //Act
            int resultadoSoma = calculadora.Soma(primeiroValor, segundoValor);
            //Assert
            Assert.Equal(10, resultadoSoma);
        }
    }
```

O primeiro método "Soma_Calculadora_RetornarValorInteiroPositivoCorreto" possui esta convenção de nomenclatura adotada para padronizar a escrita de nome de métodos de testes: nome do método + cenário de teste + resultado esperado.

O uso do atributo **Fact** significa que o método de teste não terá parâmetros.

**Theory** significa que o método terá parâmetros e para passar você deve utilizar também usar o atributo **InlineData**, como podemos ver no segundo método "Soma_Calculadora_RetornarValor10InteiroPositivo".

No framework xUnit.net existe também as palavras reservadas:

**Skip** que é a propriedade utilizada para desativar o teste. E o **Trait** que serve para organizar os testes em Grupos.

Para a escrita dos cenário de teste, utilizamos o princípio: Arrange, Act e Assert.

**Arrange** é criada a instância de classes ou moqs de interfaces para deixar claro tudo o que será utilizado no método a seguir.

**Act** é feita a ação do método desejado.

**Assert** é onde é validado se o retorno atendeu a expectativa esperada.

Antes de executar os testes, faça o build do projeto "calculadora.lib":
```
cd calculadora.lib
dotnet build
```
Para executar os testes criados acima, volte para a pasta "exemplo-teste-unidade-xunit" e acesse a pasta do "calculadora.tests":
```
cd ..
cd calculadora.tests
```
E execute o comando abaixo para rodar os cenários de testes:
```
dotnet test
```
No output do terminal será exibido quantos testes passaram ou falharam:

```Bash
A total of 1 test files matched the specified pattern.

Passed!  - Failed:     0, Passed:     4, Skipped:     0, Total:     4, Duration: 7 ms
```

# Cobertura de testes com coverlet

Acesse o diretório do projeto de teste:
```
cd calculadora.tests
```
Execute o comando abaixo para adicionar ao projeto de testes o **coverlet**:
```
dotnet add package convert.collector
```
Comando para instalar o pacote do **reportgenerator**:
```
dotnet tool install -g dotnet-reportgenerator-globaltool
```
Comando para executar os cenários de testes com o parâmetro de cobertura de código:
```
dotnet test --verbosity minimal --collect:"XPlat Code Coverage"
```

Acesse o diretório com o *guid* gerado na última execução:
```
cd TestResults/{guid}
```

Execute o comando dentro da pasta *guid* acima:
```
reportgenerator "-reports:coverage.cobertura.xml" "-targetdir:coveragereport" -reporttypes:Html
```
Acesse a pasta que foi criado TestResults/{guid}/coveragereport/index.html e abra no navegador o index.html para visualizar a cobertura de código do projeto:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qq5nkgzjuds4nqeo6bi6.png)

Referências:
https://dotnet.microsoft.com/download
https://docs.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-dotnet-test
https://xunit.net/docs/getting-started/netcore/cmdline
https://github.com/coverlet-coverage/coverlet
https://github.com/danielpalme/ReportGenerator

Código fonte do projeto de exemplo: https://github.com/rodrigo-source/exemplo-teste-unidade-xunit