Aplicando Conceitos TDD em .NET
Published: 2024-01-04 18:17:26


O Test-Driven Development é uma prática onde desenvolve-se um projeto ou parte dele pensando, primeiramente, em testes. O próprio nome traduzido já é uma auto-explicação, Desenvolvimento Dirigido por Testes. Tal prática tornou-se popular e, consequentemente, muito utilizada devido a garantia de funcionamento e qualidade de itens de desenvolvimento entregues.

Neste contexto, surge algumas perguntas, tais como:

**Qual a vantagem em desenvolver assim?**

- Maior cobertura de testes no código
- Garantia que os requisitos solicitados funcionem
- Qualidade do código (onde o próprio código de testes traz informações sobre a qualidade do código produzido)
- Garantia da entrega de um produto com maior qualidade

**Qual a diferença entre utilizar TDD e criar os testes após o desenvolvimento?**
A qualidade final de um código está com base nos testes criados. A diferença entre a maneira que cria-se os testes está no retorno de feedback do teste para o desenvolvedor.

Se um programador começa a criar os testes primeiro, ele recebe feedback constantemente, pois o mesmo consegue dividir seu trabalho em pequenas tarefas. Onde o mesmo consegue ter os seguintes passos:

- Escrever um teste
- Implementar um pedaço da funcionalidade
- Executar o teste

A cada teste escrito ele recebe um feedback. E, com isso, fica fácil de alterar o código feito.

Quando o programador desenvolve primeiro e depois, ao final, cria os testes, ele não recebeu nenhum feedback. E ao criar os testes, caso tenha que realizar alguma alteração, a mesma pode ser complexa e trabalhosa e levar um tempo maior para ser feita, custando cara.

**Isso irá diminuir minha produtividade?**
Onde pratica-se o TDD, obviamente o desenvolvedor irá gastar um maior tempo criando testes, mas não significa ser menos ou mais produtivo.

Tal tempo gasto, é gasto de maneira inteligente. Pois os testes criados, irão perdurar até o fim do projeto/código, ou seja, irá durar por muito tempo. E, além isso, podem ser executados a qualquer momento e quantas vezes for necessário, visando a garantia do código feito.

Também, ao criar/pensar em testes primeiro, facilita as modificações no código que for preciso, como citado acima.

**Como funciona o TDD?**
TDD é uma técnica de desenvolvimento baseado em um ciclo, independente da linguagem de programação, composto por passos que são:

1. Criar um cenário de teste baseado em uma regra de negócio
2. Criar o teste baseado no cenário
3. Executar o teste criado (irá falhar)
4. Escrever o código até que o teste apresente sucesso
5. Refatorar o código desenvolvido
6. Executar o teste novamente

Basicamente, é o que está apresentado na imagem abaixo:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dmrs5xgr72if3pxmmp19.png)

---

## 🔧 Mão na massa!

**Regra de negócio**
Antes de tudo, é preciso ler e entender qual é a regra de negócio que será solicitada. Sendo assim, tem-se:

> Dado itens de produtos, é necessário permitir o cadastro de tais itens. Onde cada produto terá as seguintes informações com seus respectivos tipos:
> - Nome [string]
> - Código do produto [string]
> - Descrição [string]
> - Valor de custo [decimal]
> - Valor de venda [decimal]

> Deve-se considerar as seguintes regras, ao realizar o cadastro de algum item:
> - Os campos obrigatórios serão: 'Nome', 'Código do produto' e 'Valor de custo'
> - O campo 'Valor de custo' deve ser maior do que zero
> - A quantidade de caracteres do campo 'Nome' deve ser inferior a 100
> - A quantidade de caracteres do campo 'Descrição' deve ser inferior a 500
> - O campo 'Código do produto' deverá conter, exatamente, 6 caracteres
> - O 'Valor de venda' será calculado automaticamente, onde constituirá do 'Valor de custo' + 15% de seu valor

**Cenário de teste**
Dado a regra de negócio acima, necessita-se criar os cenários de teste. No caso, cria-se apenas um como demonstrativo, sendo ele:

> Deve-se testar um produto válido, onde apresenta-se um item composto pelos seguintes dados:

> - Nome: Notebook Acer
> - Código: 849071
> - Valor de custo: R$ 1.843,25

> Deve-se validar todos os campos, de acordo com as regras, onde o resultado deverá ser sucesso.

**Construção do teste**
Com o cenário de teste já definido, pode-se criar os testes via código, como é exibido abaixo:

```csharp
public class ProdutoTest 
{
    [TestMethod]
    [DataRow("Notebook Acer", "849071", 1843.25)]
    public void SalvarProduto_ComDadosValidos_Sucesso(string nome, string codigo, decimal valor)
    {
        //action
        Produto produto = new Produto(nome, codigo, valor);

        //assert
        Assert.IsNotNull(produto);
        Assert.IsTrue(produto.Nome == nome);
        Assert.IsTrue(produto.Codigo == codigo);
        Assert.IsTrue(produto.ValorCusto == valor);
        Assert.IsTrue(produto.ValorCusto > 0);
        Assert.IsTrue(produto.Nome.Length <= 100);
        Assert.IsTrue(produto.Codigo.Length == 6);
        Assert.IsTrue(produto.ValorVenda == 2119.7375);
    }
}
```

Analisando o código, nota-se o seguinte:

- Para que um produto exista é necessário informar o nome, código e valor de custo do mesmo. Com isso, tais campos são cobrados no construtor da classe e a mesma não deve permitir ser instanciada sem tais campos, atendendo a primeira regra de validação.
- É testado se o campo referente ao Valor de Custo é maior do que zero, atendendo a segunda regra de validação
- É testado se o campo referente ao nome tem o número de caracteres menor ou igual a 100, atendendo a terceira regra de validação
- É testado se o campo referente ao código do produto tem o número de caracteres igual, exatamente, a 6, atendendo a quinta regra
- É testado se o campo referente ao valor da venda é igual a 2119.7375, valor obtido pela fórmula descrita na regra de negócio, atendendo a sexta regra

**Execução do teste**
Após o teste já estar desenvolvido, pode-se executá-lo. Como ainda não tem-se nenhum código criado, o teste não será executado e irá dar erro de compilação.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8mxts5wz2sz6dgvg2ae.png)

**Escrita do código**
Após analisar o teste criado, deve-se desenvolver o código que irá atendê-lo, ou seja, criar a classe Produto com todos os atributos esperados.

```csharp
public class Produto 
{
    public Produto(string nome, string codigo, decimal valor) 
    {
        Nome = nome;
        Codigo = codigo;
        ValorCusto = valor;
    }

    public string Nome { get; }
    public string Codigo { get; }
    public decimal ValorCusto { get; }
    public decimal ValorVenda { get; } = ValorCusto * 1.15;
}
```

**Refatoração do código escrito**
Como o código desenvolvido está atendendo perfeitamente as regras de negócio, não será necessário refatorá-lo. Apenas se houver alguma mudança na própria regra.

**Execução novamente do teste**
Por fim, ao executar o teste novamente, nota-se que o mesmo irá ter um resultado de sucesso.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2im7bklufkt6b5whi4mu.png)

---

## Conclusão
Seguindo tais práticas, garante-se que o código desenvolvido sempre estará coberto por uma certa quantidade de testes. Onde, a cada alteração do código pode-se assegurar que o mesmo estará em funcionamento.

É válido, também, considerar que os teste não são imutáveis. Pois as regras de negócio podem sofrer alterações.

---

## Referências

- http://tdd.caelum.com.br/
- https://www.devmedia.com.br/tdd-em-csharp-na-pratica-por-onde-o-projeto-deve-iniciar/28419
- https://tableless.com.br/tdd-por-que-usar/
- https://www.eusoudev.com.br/tdd/