Red, Green, Refactor
- Red: escreva um teste pequeno que expresse um comportamento ainda ausente e confirme que ele falha pela razão esperada.
- Green: implemente a menor mudança que satisfaz o teste, sem tentar prever todas as necessidades futuras.
- Refactor: melhore o desenho mantendo os testes passando: remova duplicação, esclareça nomes ou extraia uma abstração quando a necessidade estiver demonstrada.
O ciclo funciona em incrementos pequenos. Se o teste falha por erro de compilação ou setup, corrija a causa e volte a observar o resultado; “vermelho” é útil quando confirma a lacuna que o teste pretende proteger.
Exemplo incremental
Considere uma regra que calcula o total de um pedido após desconto. Primeiro, escolha um caso simples e observável:
[Fact]
public void Aplica_desconto_percentual_ao_total()
{
var pedido = new Pedido(total: 100m);
pedido.AplicarDesconto(10m);
Assert.Equal(90m, pedido.Total);
}Implemente somente o necessário para o cenário, execute o teste, depois acrescente limites relevantes: desconto zero, percentual máximo permitido e valores inválidos. Refatore quando a sequência de exemplos revelar uma estrutura repetida ou um conceito do domínio.
O código é ilustrativo em xUnit; o construtor e as regras de validação dependem do domínio. Um teste isolado não define sozinho o comportamento correto: requisitos e exemplos precisam ser discutidos com as pessoas responsáveis pelo produto.
TDD não é escrever qualquer teste primeiro
Um teste que espiona campos privados ou replica a implementação não oferece uma especificação útil. Escreva sobre o contrato observável e mantenha cada ciclo pequeno. Se o teste só passa ao conhecer uma estrutura interna que deveria poder mudar, reveja a fronteira testada.
TDD pode melhorar feedback e ajudar a revelar interfaces necessárias; não garante boa arquitetura, requisitos corretos ou ausência de bugs. Testes de integração, segurança, usabilidade e desempenho continuam necessários onde seus riscos se aplicam.
Quando o ciclo é mais e menos útil
É especialmente útil em regras determinísticas com exemplos claros, algoritmos de domínio e comportamento que tende a regressões. Pode ser menos direto em protótipos descartáveis, exploração de uma API desconhecida ou requisitos ainda ambíguos. Nesses casos, uma spike descartável, conversa ou teste exploratório pode reduzir incerteza primeiro.
Não é preciso aplicar a mesma sequência mecanicamente a toda linha de código. O objetivo é encurtar o ciclo de aprendizado, não cumprir uma liturgia ou maximizar contagem de testes.
TDD e BDD
TDD normalmente trabalha em nível de design e código, frequentemente com testes unitários. BDD usa exemplos de comportamento para alinhar vocabulário e expectativas entre funções de negócio e técnicas. Podem ser usados em conjunto: uma especificação de alto nível orienta exemplos menores e TDD detalha a implementação. Veja BDD com exemplos e Gherkin e testes unitários em .NET.