Test Driven Development (TDD) com XUnit para C# .Net Core

Daniel Jesus
8 min readJan 5, 2020

Dando continuidade nesse tema interessante de testes e suas importâncias, iremos se aprofundar um pouco mais sobre o tema de Test Driven Development (TDD) e entraremos na parte que todo desenvolvedor gosta que é a parte técnica.

Caso esteja vendo esse post e não chegou a ver o post que trata de assuntos teóricos, eu aconselho a você dar uma lida no post anterior clicando aqui, lá explico sobre a importâncias dos testes abordando testes unitários, testes de automação e o Test Driven Development (TDD).

Ambiente de Desenvolvimento

A seguir vamos utilizar a linguagem C#, onde todos os projetos foram criados em .NET Core versão 3.0 no Visual Studio 2019. Também é importante ressaltar que conhecimentos orientação ao objeto, uma vez que iremos criar domínios e testes referentes a esses domínios.

Portanto vale ressaltar as outras ferramentas que iremos usar no nosso ambiente de Desenvolvimento que são:

  • Visual Studio 2019.
  • Framework 3.0 do .Net Core.
  • X Unit

Montando a Arquitetura de teste usando XUnit em .Net Core

Depois de entendermos no conceito o que é TDD( Test Driven Development), entraremos agora na parte técnica de como realizar uma Arquitetura de teste aplicando os conceitos vistos no post anterior.

Primeiramente iremos criar uma blank solution ou em português uma solução em branco de acordo com a imagem abaixo:

Iremos nomear de CursoOnline, pois iremos tratar o assunto de vendas de cursos online como se fosse uma especificação técnica.

Depois da solução criada, iremos abrir o diretório da solução no próprio sistema operacional, que no meu caso é o Windows.

Depois de abrirmos o diretório, iremos criar duas pastas.

A primeira pasta iremos nomear como “src” que será responsável pelo projeto de aplicação e no caso da segunda pasta iremos nomear como “test” que será responsável pelo projeto de testes.

Depois de criarmos essa organização de pastas, iremos criar o projeto de XUnit em .Net Core chamado “CursoOnline.Domain.Test” e o caminho iremos informar a pasta que criamos com o nome “test”.

No caso da aplicação iremos criar um projeto de biblioteca de classe referente a um domínio do meu curso online.

Após criarmos esses dois projetos, nesse exato momento iremos trabalhar primeiramente no projeto de teste aplicando os conceitos de Test Driven Development (TDD).

Iremos realizar a criação de pastas para separarmos os domínios que serão testados referente a nossa aplicação. Portanto iremos criar uma pasta chamada de “Cursos” e dentro dela iremos criar uma classe chamada “CursosTest.cs” que será responsável por fazer as coberturas dos nossos testes unitários para o domínio de Cursos.

Agora iremos aplicar o Test Driven Development (TDD) na classe que criamos, com isso podemos dizer pra cada classe de domínio do sistema que estamos construindo, um teste é criado antes.

Então iremos realizar alguns critérios referentes a regra negócio, para que possamos desenvolver os testes aplicando o conceito de Test Driven Development (TDD):

Critérios de aceitação

Preciso de um sistema que administre os cursos onlines, pra isso preciso criar e editar para esses cursos antes da abertura de matriculas.

- Criar um curso com nome, carga horária, publico alvo e valor do curso

- As opções para o público alvo são: Estudante, Universitário, Empregado e Empreendedor.

- Todos os campos do Curso são obrigatórios.

Criando o teste unitário do domínio curso

Portanto o que restou foi a criação dos testes, que iremos realizar de acordo com critérios de aceitação que sugeri em cima.

Na primeira parte do critério de aceitação informa que é preciso criar um teste responsável por validar a criação de um novo curso. Para isso o curso deverá ter as seguintes propriedades:

nome, carga horária, publico alvo e valor do curso.

Então na classe que criamos chamada “CursoTest” iremos criar um cenário de teste que atenda esse critério. Então criei um método de teste que valida a criação do objeto curso que irá passar as informações (nome, carga horária, publico alvo e valor do curso) dentro do construtor da classe curso.

Mas como vimos na imagem a abaixo ainda não existe a classe “Curso” e com isso criamos um cenário de teste usando os conceitos de Test Driven Development (TDD).

No caso desse novo teste que criamos inicialmente falha, já que ainda não temos a implementação da funcionalidade em questão e, em seguida, implementamos a funcionalidade para fazer o teste passar!

Criando o domínio curso

Como já criamos o teste primeiro, agora entraremos no desenvolvimento da classe curso, com isso para de acusar erro em nosso teste que acabamos de criar.

Executando o primeiro teste

Após da criação do domínio e do teste, agora iremos executar o teste via console do visual studio para verificarmos se está tudo bem com nosso código.

Como está mostrando a imagem abaixo, existe um console de teste do próprio visual studio, com isso iremos visualizar e executar com o botão direito na opção “Run”ou em português “Rodar”.

A execução desse teste, podemos visualizar que o teste está passando de acordo com a imagem abaixo:

Utilizando a biblioteca ExpectedObjects

Nesse momento irei mostrar essa biblioteca que gosto de usar para os testes que estou criando que é chamada de ExpectedObjects para que possamos evitar uma quantidade grande de comandos de Asserts no nosso código.

No nuget da Microsoft, podemos encontrar essa biblioteca e adicionar no nosso projeto de teste “CursoOnline.Domain.Test”. De acordo com a imagem abaixo:

Após adicionarmos a biblioteca iremos realizar alguns ajustes no nosso código. Pois tiraremos as variáveis e criaremos um objeto anonimo com os mesmos valores e também removeremos os “Asserts.Equal” para colocar a linha de código “cursoEsperado.ToExpectedObject().ShouldMatch(curso);” que compara o objeto anônimo com o objeto que estamos esperando utilizando a biblioteca que acabamos de adicionar. De acordo com a imagem abaixo:

Refaturando o público alvo

Como todo código é preciso refaturar, com isso vamos melhorar a questão do público alvo. Ao invés de usarmos string iremos criar um enum que será responsável por informar que tipo de publico alvo possuímos na venda de um curso.

Com isso devemos mudar a propriedade publico alvo e o construtor da classe Curso de acordo com a imagem abaixo:

Tratando os parâmetros inválidos

Como toda aplicação devemos tratar os parâmetros inválidos que são passados pelo usuário, com isso iremos implementar tratamentos para a validação de entrada de dados incorretas.

Iremos começar na validação do nome do curso que verificara se o nome é diferente de nulo e vazio. Pra isso usaremos “Theory” ao invés do “Fact”, pelo motivo de usarmos uma função chamada “InlineData” que informará os valores que queremos passar que serão nulo e vazio.

Portanto nosso domínio não possui essa validação e pra isso deverá ser implementada de acordo com a imagem abaixo:

Agora iremos validar a carga horária e o valor do curso, pra isso precisamos criar os testes referentes a essas validações.

Melhorando os asserts para exceptions

Para finalizarmos com chave de ouro, vamos melhorar esses últimos trechos de código que acabamos de implementar, que se trata de capturarmos a mensagem de erro e depois validarmos de acordo com imagem abaixo:

Para evitarmos isso, é preciso realizar um novo método extensão (Os métodos de extensão permitem “adicionar” métodos a tipos existentes sem criar um novo tipo derivado, recompilar ou modificar o tipo original. Os métodos de extensão são um tipo especial de método estático, mas são chamados como se fossem métodos de instância no tipo estendido. Para o código do cliente escrito em C #, F # e Visual Basic, não há diferença aparente entre chamar um método de extensão e os métodos realmente definidos em um tipo.).

Pra isso vamos criar uma nova pasta no projeto de teste chamado de “utilidades”, que dentro dessa pasta iremos criar uma classe que terá um método de extensão da classe “ArgumentException” de acordo com a imagem abaixo:

Método de extension da classe ArgumentException

Nesse caso, iremos remover a variável “mensagemErrorDominio” e iremos chamar o método extensão dentro da classe “ArgumentException”. Porém vou mostrar o antes e depois para que vocês possam ter entendimento melhor.

Antes

Depois

Conclusão

O grande objetivo deste artigo foi mostrar e explicar um pouco da importância dos testes e também explicar a importância do Test Driven Development (TDD) no nosso dia a dia.

Espera-se que este artigo tenha contribuído com o conhecido que foi passado aqui e ter ajudado muitas pessoas que tem dúvidas ou dificuldades para implementar um arquitetura com Test Driven Development (TDD) que realmente atenda.

Recomendo que leiam artigos referentes a “Test Driven Development (TDD)” para que possam abranger o conhecimento nesse assunto.

GitHub

Deixo pra quem tem interesse o código que desenvolvemos nesse post.

Referências:

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

Daniel Jesus
Daniel Jesus

Written by Daniel Jesus

Sênior Software Engineer, Technical Writer and Speaker, Microsoft Certified Professional

No responses yet

Write a response