TDD (Test Driven Development) é um paradigma de desenvolvimento de software que visa otimizar o processo de desenvolvimento de software. Resumindo: desenvolver orientado por testes.
E como isso funciona?
O TDD tem um passo a passo a ser seguido, sendo ele um ciclo de repetição:
Fonte: marsner.com
1. Escreva um teste que inicialmente não vai passar - Vamos supor que você é um desenvolvedor frontend e precisa implementar uma nova página de login. Você recebe uma documentação com os Use Cases e um protótipo dessa página.
Normalmente, sem o TDD, a maioria dos desenvolvedores leem a documentação (ás vezes nem isso rs) e começam o desenvolvimento, visando alcançar o que foi solicitado, e assim que concluído, fazem os testes visando atender o que foi desenvolvido, e não visando a documentação, e isso é falho (cenários do que foi solicitado podem ser esquecidos).
Com o TDD, esse processo é invertido, ou seja, tudo começa pelo teste. Neste passo você o Use Case e faz o teste, e roda. O teste irá quebrar, porque o desenvolvimento ainda não foi realizado.
2. Faça o seu teste passar - Essa é a hora de botar a mão na massa. Usando o teste como um guia, você irá desenvolver o código, visando a simplicidade. Assim que o teste passar, este passo foi finalizado.
3. Refatore o seu código - Esse é um passo que vejo muitos desenvolvedores ignorando, ou não dando a devida atenção no TDD, e ao cometer esse erro, o TDD perde o seu sentido.
Neste passo, devemos refatorar nosso código produzido no passo anterior, aplicando conceitos, design patterns e boas práticas de desenvolvimento, visando uma aplicação mais robusta, escalável e de fácil manutenção. É aqui que se encontra a aplicação do Clean Code.
Após o passo 3, verifique se o teste está passando. Se sim, você volta ao passo 1, agora partindo do próximo Use Case e assim sucessivamente. Caso contrário, verifique sua refatoração, porque você acabou de gerar um bug rs.
// Exemplo prático de ciclo TDD com Vitest / Jest:
import { describe, it, expect } from 'vitest';
import { validateUserCredentials } from './auth';
describe('validateUserCredentials', () => {
it('deve validar com sucesso credenciais corretas', () => {
const result = validateUserCredentials('dev@alannunes.com', 'SuperSenha!2026');
expect(result.isValid).toBe(true);
});
});
Minha experiência com TDD
Conhecendo os testes unitários e a sua importância
Estou no mercado de desenvolvimento desde meados de 2016, e como um desenvolvedor frontend, nas empresas em que passei, não havia o hábito em fazer testes unitários no frontend. Infelizmente até hoje (2022) é uma cultura muito forte no Brasil, porém vejo o cenário sendo mudado aos poucos. Com isso, acabei “indo na onda” e demorei um tempo para conhecer mais sobre testes unitários e seus benefícios.
No processo de aprendizado e aplicação de testes unitários no meu dia a dia (certamente, sem o uso do TDD), comecei a entender o quão melhorava a eficácia do meu código, e o teste em si se tornava meu aliado, meu braço direito, me ajudando a entregar um código com mais qualidade e com menor probabilidade de entregar um problema em ambiente produtivo.
Como os testes unitários podem ser ainda melhor no meu dia a dia?
Comecei a me perguntar se isso era o suficiente, ou poderia ser ainda melhor… Lembro como se fosse hoje, que nos dias de estudos, de meetup ou eventos de tecnologia, escutava muito se falar de um tal de TDD, que até então eu desconhecia.
Um dia, participei de um evento do ABC - São Paulo, chamado ABCDev, em que uma das palestras na qual eu assisti falava exatamente sobre TDD. Então minha cabeça simplesmente “explodiu” rs. Achei muito interessante a princípio, mas dúvidas surgiam, principalmente sobre a demora de entregar determinada feature com toda essa “burocracia” de testes.
Após tentar colocar o TDD em prática, errando bastante (sim, errando - eu era um dos devs que estava pulando a parte de refatoração do código de maneira adequada, e não só isso, saía do ciclo pelo meu vício de desenvolvimento NÃO orientado por testes, aplicava o TDD em tarefas gigantes, sem seguir os Use Cases e em cenários que não faziam sentido), percebi que algo estava errado e comecei a estudar mais sobre o assunto, ao invés de sair aplicando um termo que conhecia superficialmente.
Encontrei muito conteúdo valioso (vou deixar no final da publicação algumas referências) sobre o assunto e onde eu estava errando afinal. Um dos conteúdos que mais me ajudou nisso foi, sem sombra de dúvidas, os cursos do Rodrigo Manguinho, que explica como aplicar o TDD de forma eficiente.
Benefícios ao aplicar o TDD
- Melhor design de programa e maior qualidade de código
- Documentação detalhada do projeto
- TDD reduz o tempo necessário para o desenvolvimento do projeto
- Manutenção do código é mais fácil
- Solução confiável
- Economicamente melhor a longo prazo
Afinal, o TDD faz sentido?
Claramente, faz muito sentido. O TDD é uma ferramenta que impulsiona o desenvolvedor a programar melhor, a aplicar os conceitos consolidados e a ter uma visão ampla visando o projeto a longo prazo.
É importante ressaltar que não é um paradigma tão simples quanto parece de ser aplicado da melhor forma. Para aplicar o TDD, você deve estar ciente do ciclo dele e ter o conhecimento das melhores práticas de desenvolvimento. Se você não conhece o Clean Code, do criador Uncle Bob, aconselho dar prioridade nesse conhecimento e, posteriormente, juntar o TDD ao Clean Code.
Deixarei para vocês uma frase do livro Test-Driven Development: By Example, feito por ninguém menos que o criador do TDD, Kent Beck, que resume toda a percepção que eu tenho hoje sobre o assunto:
“If you’re happy slamming some code together that more or less works and you’re happy never looking at the result again, TDD is not for you. TDD rests on a charmingly naïve geekoid assumption that if you write better code, you’ll be more successful. TDD helps you to pay attention to the right issues at the right time so you can make your designs cleaner, you can refine your designs as you learn.” ― Kent Beck, Test-Driven Development: By Example