Red, Green, Refactor

  1. Red: escreva um teste pequeno que expresse um comportamento ainda ausente e confirme que ele falha pela razão esperada.
  2. Green: implemente a menor mudança que satisfaz o teste, sem tentar prever todas as necessidades futuras.
  3. 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.

Documentação e leituras relacionadas