O que é TDD (Test-Driven Development)?
Em português: Desenvolvimento orientado a testes
TDD desenvolve comportamento em ciclos de teste que falha, código mínimo que passa e refatoração.
TDD, ou Test-Driven Development, é uma prática de programação em que se escreve primeiro um teste para o próximo comportamento. O teste deve falhar, o código mínimo o faz passar e então a estrutura é refatorada com a suíte verde. Os ciclos curtos apoiam feedback e decisões de design, mas não substituem outras formas de testar e validar o produto.
Origem
Kent Beck desenvolveu TDD no contexto de Extreme Programming no fim dos anos 1990, conforme a descrição de Martin Fowler. O ciclo vermelho, verde e refatora tornou-se sua forma mais conhecida. A técnica é uma prática de engenharia, não um evento obrigatório do Scrum nem uma garantia automática de ausência de defeitos.
Fonte primária: Test Driven Development
Na prática
TDD, Test-Driven Development, é uma disciplina de programação em que um teste automatizado pequeno antecede o código de produção que o fará passar. O ciclo é conhecido como vermelho, verde e refatora: ver a falha esperada, implementar apenas o suficiente e melhorar a estrutura mantendo comportamento. Martin Fowler atribui o desenvolvimento da técnica a Kent Beck, no contexto de Extreme Programming no fim dos anos 1990. A prática relaciona programação, testes e design em ciclos curtos.
O que acontece quando falta
Sem testes próximos do código, mudanças podem exigir inspeção manual repetitiva e defeitos podem ser descobertos tarde. TDD é uma forma de criar feedback e apoiar refatoração, mas não a única. Uma equipe pode começar com testes de caracterização em código legado e combinar diferentes níveis de verificação. O objetivo é poder modificar comportamento com entendimento e risco controlado.
Como funciona TDD
TDD, Test-Driven Development, é uma disciplina de programação em que um teste automatizado pequeno antecede o código de produção que o fará passar. O ciclo é conhecido como vermelho, verde e refatora: ver a falha esperada, implementar apenas o suficiente e melhorar a estrutura mantendo comportamento. Martin Fowler atribui o desenvolvimento da técnica a Kent Beck, no contexto de Extreme Programming no fim dos anos 1990. A prática relaciona programação, testes e design em ciclos curtos.
Comece por um comportamento. Faça uma lista de casos que a funcionalidade precisa atender. Escolha o menor caso útil e escreva um teste que expresse o resultado esperado. Um teste que falha por erro de configuração não é o mesmo que falhar porque o comportamento ainda não existe. Confirmar essa distinção protege a lógica do ciclo. Testes devem ter nomes e exemplos claros para outra pessoa compreender o contrato observado.
Veja o vermelho. Execute o teste antes de implementar. A falha mostra que ele pode detectar a ausência do comportamento. Se já passa, talvez esteja testando outra coisa ou o comportamento já exista; esclareça antes de continuar. Não acrescente muitos testes falhando de uma vez para depois desenvolver tudo: o retorno rápido ajuda a localizar a causa e limita o tamanho da decisão de design.
Chegue ao verde. Escreva o mínimo de código necessário para satisfazer o teste, sem antecipar recursos futuros. “Mínimo” não significa publicar código descuidado: é uma etapa curta do ciclo, seguida por melhoria. Em alguns casos, uma implementação simples parece trivial, mas permite avançar para o próximo exemplo que exigirá generalização. Não crie abstrações para possibilidades que ainda não foram demonstradas por necessidade real.
Refatore com proteção. Com a suíte verde, elimine duplicação, melhore nomes e ajuste estrutura sem alterar comportamento observável. Rode os testes novamente. Refatorar não é acrescentar nova função; se um comportamento novo é necessário, volte ao vermelho com outro teste. Uma suíte rápida e confiável dá feedback, mas não prova ausência de defeitos em tudo o que não foi coberto.
Escolha a fronteira do teste. Um teste de unidade pode exercitar uma função ou um componente com dependências controladas. Testes de integração verificam interação com banco, rede ou outros serviços, com custo e velocidade diferentes. TDD pode ocorrer em vários níveis, mas um ciclo lento e frágil dificulta seu uso diário. Evite mocks que apenas repetem detalhes de implementação: eles podem passar enquanto o comportamento real falha.
Use exemplos para desenhar interface. Ao escrever o teste antes, a pessoa desenvolvedora consome a API antes de construí-la. Isso pode revelar nomes confusos, dependências difíceis de configurar ou responsabilidades excessivas. A melhoria de design não acontece automaticamente; requer escolhas e refatoração. Um código coberto por muitos testes pode continuar complicado se os testes só congelam sua forma atual.
Conecte ao produto. Critérios de aceitação e conversas com stakeholders ajudam a escolher comportamentos valiosos; TDD transforma uma parte desses comportamentos em feedback automatizado de engenharia. A técnica não substitui testes exploratórios, segurança, desempenho, acessibilidade ou validação de valor com usuários. Um teste verde comprova uma condição especificada, não que a condição era a certa para o produto.
Trate legado com pragmatismo. Em um sistema sem testes, talvez seja necessário criar testes de caracterização antes de alterar código. Primeiro descreva o comportamento atual que deve ser preservado; depois introduza mudança em passos menores. Às vezes a dependência rígida exige isolar uma parte do sistema. TDD não obriga reescrever tudo; pode começar em uma nova regra ou correção bem delimitada.
Avalie o efeito real. Observe defeitos escapados, facilidade de mudança, tempo de feedback e clareza dos testes. Medir apenas percentual de cobertura incentiva exercícios que não protegem o comportamento importante. A prática exige treinamento e colaboração, especialmente para escolher bons exemplos e refatorar com segurança. Se o ciclo vira ritual mecânico, investigue tamanho dos passos, qualidade da suíte e entendimento do domínio.
Exemplo de regra de desconto
Exemplo hipotético: um sistema calcula desconto para assinaturas. A equipe começa com o caso “assinatura ativa com cupom válido recebe desconto de 10%”, escreve o teste e vê falha porque a regra não existe. Implementa a condição mínima e obtém verde. Em seguida, melhora o nome da função e remove duplicação, mantendo o teste verde. Os números são ilustrativos, não regra de negócio da K21.
O próximo teste descreve cupom vencido sem desconto. Ele falha e obriga a distinguir validade do cupom. Outro exemplo cobre limite máximo de desconto. A implementação emerge de casos observáveis, enquanto a equipe discute com produto o que deve acontecer em situações não definidas. Uma dúvida sobre reembolso parcial não é resolvida inventando um teste: precisa de decisão de domínio.
Ao final, testes automatizados apoiam mudanças futuras, mas a equipe ainda realiza verificação de integração e exploração da experiência. O exemplo mostra a sequência pequena de feedback, não a promessa de que TDD sozinho garante qualidade completa.
Como praticar um ciclo de TDD
Liste casos
Identifique comportamentos e escolha o menor exemplo útil.
Escreva teste
Descreva resultado esperado de forma observável.
Confirme falha
Execute e verifique que o vermelho é pela razão certa.
Implemente
Faça o mínimo para chegar ao verde.
Refatore
Melhore a estrutura sem mudar comportamento.
Repita
Escolha o próximo caso e rode a suíte inteira.
TDD e testar depois
Em TDD, o teste antecede o próximo pedaço de código e ajuda a definir a interface e o comportamento. Testar depois também pode detectar problemas, mas não proporciona o mesmo ciclo de design dirigido por exemplos. Ambas as abordagens dependem da qualidade dos testes. A escolha não elimina teste exploratório, integração e validação com usuários; elas respondem a perguntas diferentes.
Erros comuns
- Falha pela causa errada. Um erro de ambiente não confirma o caso.
- Pular refatoração. O código cresce sem melhoria de design.
- Testar detalhes internos. Mudanças simples quebram testes frágeis.
- Confiar só na cobertura. Condições importantes podem não ser verificadas.
- Tomar teste verde por valor. A hipótese de produto pode estar errada.
Visão K21
Visão da K21
O artigo da K21 “Qualidade de software com TDD” destaca escrever testes antes do código de negócio e relaciona a prática à qualidade. Essa visão é útil, desde que não se transforme em garantia absoluta: a qualidade depende também de bons exemplos, integração, exploração e entendimento das necessidades. A sequência técnica é fundamentada nas descrições de Fowler e da Agile Alliance.
Para se aprofundar
No blog da K21
- Qualidade de software com TDD (Test Driven Development)
Introduz a escrita de testes antes do código pela perspectiva da K21.
Fontes primárias
- Test Driven Development, Martin Fowler (2023)
- TDD, Agile Alliance
Termos relacionados
Perguntas frequentes
O que significa TDD?
Significa Test-Driven Development, ou desenvolvimento orientado a testes. A pessoa escreve um teste para um pequeno comportamento antes de implementá-lo, confirma a falha, faz o código passar e refatora. O ciclo se repete. Sua finalidade é obter feedback rápido e orientar design, além de construir uma suíte de regressão.
Por que o teste precisa falhar primeiro?
A falha mostra que o teste é capaz de perceber a ausência do comportamento esperado. É importante verificar a razão: um erro de configuração não confirma que o caso foi bem escrito. Quando o teste já passa, investigue se o comportamento existe ou se a verificação não observa o que deveria. Esse passo protege a utilidade do ciclo.
TDD garante código sem bugs?
Não. Testes cobrem exemplos escolhidos e podem deixar casos, integrações ou riscos importantes de fora. Também é possível testar apenas detalhes internos e obter falsa confiança. TDD apoia feedback e refatoração, mas precisa ser combinado com revisão, testes em outros níveis, exploração e validação de que o comportamento especificado corresponde à necessidade.
TDD é obrigatório no Scrum?
Não. O Scrum Guide define responsabilidades, eventos, artefatos e compromissos, mas não prescreve uma técnica de programação. Um Scrum Team pode escolher TDD para apoiar qualidade e a Definition of Done. A decisão deve considerar produto, habilidade da equipe, arquitetura e custo de feedback, sem confundir prática de engenharia com regra do framework.
Como começar TDD em código legado?
Escolha uma alteração pequena, identifique o comportamento atual que precisa ser preservado e crie testes de caracterização quando possível. Isole dependências difíceis gradualmente e avance em ciclos curtos. Não é necessário reescrever o sistema inteiro antes de começar. Priorize áreas em que mudanças frequentes e defeitos justificam o investimento em feedback automatizado.
