Desenvolvimento Orientado a Testes
Tags: testing, programming, productivity, webdev
Published: 2023-12-18 15:59:47

Durante o desenvolvimento de um _software_, é essencial entregar um _software_ que funcione corretamente, com qualidade e no prazo estabelecido. Para garantir estes pontos, é importante testarmos nossos _softwares_ com o intuito de encontrar possíveis falhas. E com essas possíveis falhas encontradas, poderemos corrigir esses problemas antes de chegar ao usuário final.

Mas, testar um _software_ corretamente não é algo tão simples como pode parecer. Por isso, existem diversas metodologias que visam testar os diferentes componentes de uma solução de software de maneira correta. Algumas destas metodologias visam testar a integração entre os componentes de um _software_, enquanto outras visam testar cada um dos componentes de maneira isolada.

Uma das metodologias que mais estou utilizando no desenvolvimento dos meus projetos é o **TDD**. No **TDD**, você codifica o teste antes mesmo do código existir.

## O que é a sigla TDD?

**TDD** é uma sigla para _**Test Driven Development**_, ou _Desenvolvimento Orientado a Testes_. 
A ideia do **TDD** é que você trabalhe em ciclos. Estes ciclos ocorrem na seguinte ordem:

- Primeiro, escreva um teste unitário que inicialmente irá falhar, tendo em vista que o código ainda não foi implementado;
- Crie o código que satisfaça esse teste, ou seja: implemente a funcionalidade em questão. Essa primeira implementação deverá satisfazer imediatamente o teste escrito no ciclo anterior;
- Quando o código estiver implementado e o teste satisfeito, refatore o código para melhorar pontos como legibilidade. Logo após, execute o teste novamente. A nova versão do código também deverá passar sem que seja necessário modificar o teste escrito inicialmente.

_Vale ressaltar que **TDD** não é uma forma de escrever teste: ele é uma metodologia para desenvolvimento e escrita código._

### Ciclo do TDD

A representação mais clara sobre como funciona o **TDD**, pode ser visualizada na imagem abaixo:

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

Perceba a existência dos três ciclos:

- _**Red:**_ escreva um pequeno teste automatizado que, ao ser executado, irá falhar;
- _**Green:**_ implemente um código que seja suficiente para ser aprovado no teste recém-escrito;
- _**Refactor:**_ refatore o código, a fim dele ser melhorado, deixando-o mais funcional e mais limpo.

Para realizar o teste em cada funcionalidade do seu código, você sempre irá seguir estes ciclos. Estes ciclos são comumente referenciados como _**red-green-refactor**_ ou _**red-green-blue**_.

A ideia é que você utilize estes ciclos para **testes unitários** ⇾ testes estes que visam avaliar o comportamento de classes e métodos em específico. Você irá identificar quais são os comportamentos esperados dos métodos a serem desenvolvidos. Ao invés de implementar o código inicialmente, você irá criar o código de teste ligado a essas classes e métodos que você deseja implementar. 
Como esse código ainda não estará devidamente implementado, o teste irá falhar (_**red**_), para que em seguida você faça a implementação dessa funcionalidade. Com a implementação, é esperado que esse teste passe (_**green**_). No final, você pode melhorar esse código, evitando duplicidade e trechos de código desnecessários (_**refactor**_) e irá fazer o teste novamente, onde ele deve passar. Assim você terá um código funcional e já devidamente testado.

### Quais os benefícios?

Existem diversos benefícios ao escrevermos os testes antes mesmo de realizar uma implementação. Um dos benefícios é que, como você vai saber o que o código precisa fazer antecipadamente, você acaba evitando escrever código demasiadamente complexo ou que não siga os pré-requisitos de negócio.

Além disso, se você for deixar para testar as funcionalidades do seu código depois, você pode acabar não realizando os testes como deveria. Isso aumenta o risco de, por exemplo, realizarmos alterações no código por conta de testes que não passaram, aumentando substancialmente a possibilidade de introduzirmos problemas com estas alterações. Escrevendo os testes na etapa inicial, pode até parecer que acabamos tendo uma tarefa a mais a ser desempenhada; porém, no fim, seu software terá menos possibilidade de falhas, além de você acabar desenvolvendo código com mais qualidade.

### Ferramenta para escrita dos testes de unidade

Para as principais linguagens e bibliotecas de programação, cada uma possuem sua própria ferramenta para escrita dos cenários de teste de unidade, onde se utiliza a metodologia **TDD** de forma prática. Abaixo, é listado alguns exemplos:

- **.NET** - [NUnit](https://nunit.org/)
- **PHP** - [PHPUnit](https://phpunit.de/)
- **Node** (JavaScript) - [Jasmine](https://jasmine.github.io/)
- **Java** - [JUnit](https://junit.org/junit5/)
- **Python** - [PyUnit](https://wiki.python.org/moin/PyUnit)
- **React** - [Jest](https://jestjs.io/pt-BR/), [Testing-Library](https://testing-library.com/), [Vitest](https://vitest.dev/)