Aprendendo testes unitários com xUnit e Shouldly
Bom dia. Boa tarde. Boa noite.
Falarei sobre algo que por muito tempo ignorei: testes. Não aqueles testes manuais, mas sim os testes automatizados.
O que vamos abordar aqui são os testes unitários. Para cada funcionalidade do seu código será necessário criar um teste. Assim garantimos que aquele seu trecho está funcionando como deveria.
Os testes unitários não se aplicam somente a novo projetos também se aplicam ao legado, imagine criar testes unitários durante uma refatoração ? Seria uma estratégia interessante.
O que ganhamos com os testes unitários?
- Confiabilidade
- Automatização
Uma das etapas da entrega de software automatizada é a execução de testes automatizado, utilizando os testes unitários e integrados para garantir que aquele “pacote” está pronto para ser publicado em produção, por exemplo.
O que utilizaremos para praticar os testes unitários ?
- Visual Code
- C#
- xUnit
- Shouldly
- .NET Core
Sobre o Shoudly: É uma biblioteca que uso no meu cotidiano, ele faz com que a escrita fique mais fluente e entendível.
Sobre o xUnit: Framework de testes unitários para o .NET. Existem outros como por exemplo o MSUnit e NUnit.
Estrutura
Vamos ver como ficaria a estrutura de diretórios de uma solução com projetos de testes:
/Solution.sln
|
|---- Projeto1
| |---- Class1.cs
| |---- Projeto1.csproj
|---- Projeto2
| |---- Projeto2.csproj
|---- Projeto1.Tests
| |---- Class1Test.cs
| |---- Projeto1.Tests.csproj
|---- Projeto2.Tests
| |---- Projeto2.Tests.csproj
Como vemos acima, todo projeto criado tem também um projeto destinado a testes. E seguimos a convenção [Name].Tests para definir o nome do projeto e o sufixo Test para as classes de testes.
Então vamos partir para a prática !
Criação dos projetos
Abra o terminal de sua escolha e execute as etapas abaixo:
Criar um novo arquivo de solução, quando informado o parâmetro -o, será criado uma nova pasta com o valor informado, senão utilizará o nome do diretório atual:
dotnet new sln -o project-euler-csharp
cd project-euler-csharp
Criar um projeto do tipo Class Library, a mesma ideia do parâmetro -o se aplica aqui também:
dotnet new classlib -o Problems
Criar o projeto do tipo Test já com as dependências necessárias do xUnit:
dotnet new xUnit -o Problems.Tests
Adiciona as referências dos projetos recém criados ao arquivo de solução:
dotnet sln add Problems/Problems.csprojdotnet sln add Problems.Tests/Problems.Tests.csproj
Iniciar uma nova instância do Visual Code no diretório atual:
code .
Codificação
Vamos começar por um bem básico para entender o xUnit e o Shouldly.
No projeto Problems, renomeie o arquivo Class1.cs para Helpers.cs — não esqueça de também alterar o nome da classe— e vamos alterar a classe para static e acionar um método de soma que recebe dois argumentos do tipo inteiro.
O intuito dessa classe é oferecer diversos métodos auxiliares para resolver nossos problemas.
O resultado da classe ficaria assim:
Preparando o projeto de teste
Antes de criamos o teste unitário devemos adicionar a referência do projeto Problems e também o pacote NuGet Shouldly.
No terminal do Code execute os códigos abaixo
dotnet add .\Problems.Tests\Problems.Tests.csproj package Shouldly
dotnet add .\Problems.Tests\Problems.Tests.csproj reference .\Problems\Problems.csproj
Então vamos renomear o arquivo UnitTest1.cs para HelpersTest.cs — não se esqueça de alterar também o nome da classe.
Criando testes
Apague o método que foi gerado pelo template e vamos criar um novo: Sum_ShouldBeSuccess.
O nome do teste é importante, pois ele define o que estamos testando e não devemos de esquecer de testar também a falha !
O resultado do sucesso seria esse:
Observações no uso do Shouldly:
- Adicionar o using do Shouldly, pois assim podemos utilizar os extensions methods.
- Note que para fazermos a asserção do teste utilizamos o método ShouldBe(), existem outros como ShouldBeTrue(), ShouldBeFalse(), especificos para trater Exceptions. A documentação tem a lista completa dos métodos e exemplos.
Fact é um atributo do xUnit que nos permite escrever um teste que prova algo, ou seja, quando eu somo 1 + 2 o resultado deve ser 3. Os valores testados são hardcoded.
Quando não utilizamos a biblioteca Shouldly a asserção deve ser feita utilizando o método estático Assert.Equal(expectedValue, value):
Podemos notar a diferença tanto na leitura quanto na escrita da asserção.
Além do atributo Fact existe também o Theory que nos permite testar vários casos, ou seja, você especifica os argumentos que deseja através de outro atributo chamado InlineData.
Observações do uso do InlineData:
- O número de argumentos no método deve ser igual ao número de itens informados no atributo.
- O tipo do argumento é um array de object, então podemos passar qualquer tipo.
- É possível utilizar quantos InlineData quisermos.
- O InlineData é utilizando juntamento com o Theory
Rodando os testes
Para rodar os testes temos duas maneiras:
- Code
- Linha de comando
Para executar um único teste existem as opções de Run e Debug acima da definição de cada método. E para a execução de todos existe a opção Run All e Debug All acima da definição da classe.
Os resultados aparecerão no Output Window do Code.
Pela linha de comando basta executar na linha de comando do Termial:
dotnet test .\Problems.Tests\Problems.Tests.csproj
Esse comando irá executar todos os testes do projeto e exibirá os resultados.
Existe uma extensão para Code chamada .NET Core Test Explorer que adiciona uma nova aba para exibição e execução dos testes criados.
O código fonte encontra-se nesse repositório.
No próximo artigo falarei sobre como praticar teste unitário utilizando o Project Euler.