TDD com IA: por que deixar a IA escrever o teste e o código ao mesmo tempo quebra a verificação?

TDD com IA funciona, mas quebra num ponto específico: quando a mesma conversa escreve o teste e o código, o teste deixa de ser verificação e vira espelho do que a IA acabou de gerar. O ciclo Red, Green, Refactor existe justamente pra provar que o teste detecta a ausência do comportamento, e é o Red que a gente pula quando pede tudo de uma vez. A saída é separar os papéis: descrever o comportamento esperado, pedir o teste sem implementação, ver falhar, e só então pedir o código que passa sem tocar nos testes
Quando a mesma IA escreve o teste e o código na mesma conversa, o teste para de ser verificação e vira espelho
Se liga nisso: tu pede uma feature, a IA gera a implementação, tu completa com um "e escreve os testes também", tudo fica verde de primeira e bate aquela sensação de dever cumprido
Só que o teste não conferiu nada
Ele foi escrito olhando pro código que já estava ali, então ele descreve o que o código FAZ, não o que o código DEVERIA fazer
Se o código nasceu com bug, o teste nasce certificando o bug
Esse post é sobre essa armadilha e sobre como separar os dois papéis na conversa, usando o que a documentação e os estudos já sustentam…
O que o TDD garante e por que a ordem importa
TDD foi criado (ou, nas palavras do próprio autor, redescoberto) por Kent Beck no fim dos anos 1990, dentro do Extreme Programming, e virou livro em 2003 com o Test Driven Development: By Example
O ciclo é aquele que todo mundo já viu: Red, Green, Refactor
Escreve o teste que falha, faz passar, refatora
Agora a parte que quase todo mundo trata como formalidade chata: o Red
O valor do TDD não está em ter teste
Está em ter um teste que FALHOU antes do código existir
O Red é a única prova de que aquele teste consegue enxergar a ausência do comportamento
Teste que nunca falhou é teste não testado, e um teste não testado é só código extra rodando na sua pipeline
É tipo alarme de incêndio: se tu nunca apertou o botão de teste, tu não tem alarme, tu tem uma caixinha branca no teto 😀
Formação Agentes de IA
Domine a criação de Agentes de IA e Venda para Empresas
- 402 aulas
- 32 projetos
- 38h 19min
O teste que nasceu do código: como identificar e como evitar
Os sintomas
Dá pra reconhecer esse tipo de teste sem ler linha por linha:
- ficou verde de primeira, sem nunca ter passado pelo vermelho
- as asserções são genéricas, do tipo "não é nulo", "tem alguma coisa aqui"
- aparece print revelando valor no lugar de asserção formal
- cobre exatamente o caminho feliz que o código já implementa, e só ele
- toda borda que o código não tratou também não aparece no teste
Repara no padrão: o teste tem exatamente o mesmo campo de visão do código
Não é coincidência, é herança
A causa: o código bugado no contexto contamina o teste
Tem nome pra isso na literatura: efeito de desorientação (misguidance effect)
O artigo Evaluating and Mitigating the Misguidance Effect of Buggy Code in LLM-Generated Unit Tests, de Junda Zhao, Shurui Zhou e Eldan Cohen, aceito na ISSTA 2026, mede justamente isso: quando o LLM recebe o código bugado dentro do prompt, ele passa a gerar mais testes que afirmam o comportamento ERRADO como se fosse o correto, e gera menos testes capazes de encontrar o bug
Ou seja, o problema não é a IA ser ruim de teste
O problema é ela ser boa demais em concordar com o que está na tela
O código vira a especificação, e a especificação de verdade (o que o negócio pede) nunca entrou na conversa
Como evitar
A mitigação que o próprio paper propõe é direta: gerar o teste a partir de uma especificação de comportamento, não do código
Na prática isso significa que a ordem do seu prompt é a sua metodologia agora
Se o código entra no contexto antes do teste, tu já perdeu a independência da verificação, não importa quantos testes vierem depois
Teste humano x teste de agente: o que os estudos mediram
Um estudo empírico comparou testes escritos por humanos e por agentes de IA em projetos open source, analisando 204.673 artefatos de teste (24.941 de humanos e 179.732 de agente, do dataset AIDev)
| Métrica | Humano | Agente de IA |
|---|---|---|
| Asserções fortes | 88,1% | 85,37% |
| Asserções ambíguas ou não classificadas | 1,46% | 11,58% |
| Variedade de checagem de borda | 0,32 | 0,62 |
| Teste de null-safety | 8,3% | 13,40% |
Olha que interessante: em asserção forte o agente empata quase redondo, e em borda e null-safety ele até faz MAIS que o humano
O buraco está numa linha só: asserção ambígua ou não classificada, 1,46% contra 11,58%
É ali que a verificação vaza
Outro estudo, aceito na MSR 2026 (pesquisa do Nara Institute of Science and Technology com a University of Groningen), mediu que agentes de IA assinaram 16,4% de todos os commits que adicionam teste nos projetos estudados
Os testes de IA aparecem mais densos em asserções e com cobertura comparável, mas com risco do smell Assertion Roulette (aquele teste com um monte de asserção sem mensagem, que quando quebra tu não sabe qual delas quebrou)
E tem um terceiro, sobre trajetórias de agentes no SWE-bench Verified, com 6 LLMs analisados: agentes que resolvem o bug escrevem testes praticamente na mesma taxa dos que falham
Experimentos controlados aumentando ou diminuindo a escrita de testes não produziram mudança estatisticamente significativa na taxa de resolução
E os agentes favorecem prints reveladores de valor em vez de asserções formais
A leitura honesta dos três é essa: não é que "IA testa mal"
IA testa DIFERENTE
Volume de teste gerado não compra correção, e ambiguidade de asserção é onde a garantia evapora
Como separar os dois papéis na conversa com a IA
A documentação oficial do Claude Code trata TDD como workflow recomendado e descreve o fluxo com uma ordem bem específica
Ela instrui a pedir os testes a partir de pares entrada/saída esperados, rodar e confirmar que FALHAM, dizer explicitamente ao Claude para NÃO escrever implementação nessa etapa, e só depois pedir o código que passa sem modificar os testes
Bora ver na prática?
- Descreva o comportamento em pares entrada/saída, sem mostrar implementação
Nada de colar o arquivo bugado antes
A especificação vem primeiro, sozinha:
Comportamento esperado da funcao aplicarDesconto(valor, cupom):
- (100, "OFF10") -> 90
- (100, "INVALIDO") -> erro de cupom invalido
- (0, "OFF10") -> 0
- (100, null) -> 100
O erro comum deste passo: colar o código junto "pra ela entender melhor o contexto"
É exatamente esse gesto que dispara o efeito de desorientação
- Peça os testes e proíba a implementação nessa etapa, com todas as letras
Escreva SOMENTE os testes para o comportamento acima.
Nao escreva nenhuma implementacao nesta etapa.
Nao crie stub, mock da funcao nem arquivo de codigo de producao.
O erro comum deste passo: deixar a proibição implícita
Se tu não fala, ela ajuda, e ajudar aqui significa criar a implementação junto e matar o Red
- Rode os testes e confirme que eles FALHAM
Esse passo é inegociável
Teste que passa antes do código existir está testando outra coisa (ou nada)
O erro comum deste passo, e é o mais grave de todos: pular o Red porque "já deu pra ver que tá certo"
Sem o vermelho, tu não tem TDD, tu tem código com anexo
- Só então peça o código que passa, sem modificar os testes
Agora implemente o codigo que faz esses testes passarem.
Nao altere nenhum arquivo de teste.
O erro comum deste passo: aceitar teste "ajustado" no meio do caminho
Quando a IA mexe no teste pra fazer passar, o placar continua verde e a verificação já morreu
- Use o plan mode pra especificar sem tocar em arquivo
O Claude Code tem modo de planejamento em que ele lê, analisa e propõe um plano sem editar arquivos de código
O Shift+Tab cicla entre os modos Default, Auto-accept edits e Plan mode, e em plan mode as edições ficam bloqueadas até tu aprovar o plano
Dá pra desenhar a especificação inteira ali, com a mão dele amarrada
O erro comum deste passo: sair do plan mode antes de fechar a especificação, e aí o primeiro arquivo criado já é o de implementação
- Ponha quem escreve o teste em outro contexto
O Claude Code suporta subagentes com contexto próprio, gerenciados pelo comando /agents, definidos em arquivos Markdown com frontmatter YAML
Os de projeto ficam em .claude/agents/ e os de usuário em ~/.claude/agents/, com name e description obrigatórios no frontmatter
A ideia é simples: quem escreve o teste não deveria ser quem acabou de escrever o código, porque o código na janela é justamente o contaminante
É o mesmo raciocínio de quando tu abre duas sessões no mesmo projeto ou precisa manter dois projetos sem misturar contexto: contexto separado não é frescura, é o que garante que a segunda opinião seja de fato uma segunda opinião
O erro comum deste passo: criar o subagente e mesmo assim colar a implementação no prompt dele
Aí tu só trocou o crachá, o contaminante entrou igual
- Transforme a regra do prompt em permissão de verdade
Até aqui tudo depende de tu pedir bonitinho, e pedido não é limite
As permissões do Claude Code no settings.json têm regras allow, ask e deny, avaliadas nessa ordem de precedência
O deny vem primeiro e prevalece sobre um allow, e a primeira correspondência decide
Dá pra usar isso pra tornar a proibição do passo 2 e a do passo 4 uma barreira concreta, não um pedido educado no meio da conversa
O erro comum deste passo: confiar só na instrução em linguagem natural
Instrução é intenção, permissão é limite
- Rode os testes automaticamente depois de cada edição
Lembra que o passo 3 é inegociável? Então, dá pra tirar ele da tua memória e botar na máquina
O Claude Code tem hooks de ciclo de vida, e o PostToolUse roda depois que uma ferramenta (incluindo as de edição de arquivo) é executada com sucesso
Ele é configurado no settings.json com matcher de ferramenta e pode disparar lint, formatação ou testes
Assim tu não depende do relatório dela sobre o resultado, tu vê o resultado
O erro comum deste passo: aceitar "os testes passaram" como texto na conversa
Saída de execução é prova, frase não é
Quando separar os papéis vale o atrito e quando não vale
Isso tudo custa tempo, e seria desonesto fingir que não
Então vale calibrar
Vale o atrito quando:
- é regra de negócio com borda, valor zero, null e caso limite (o lugar onde asserção ambígua machuca mais)
- é correção de bug, que é literalmente o cenário do efeito de desorientação: o código errado está na tela, e é dele que a IA vai tirar a noção de "correto"
- o código vai ser mantido por outra pessoa, que amanhã vai confiar naquele teste verde sem saber como ele nasceu
- é caminho crítico: cobrança, permissão, cálculo que vira número na conta de alguém
Não vale quando:
- é rascunho descartável, daqueles que morrem na mesma tarde
- é spike exploratório, tu ainda nem sabe qual é o comportamento certo pra especificar
- é script de uso único, roda uma vez e vai pro lixo
E deixa claro: isso é escolha de RISCO, não de moral
Ninguém é melhor dev por fazer TDD no script que converte um CSV uma vez na vida 🙂
Vale fazer TDD com IA?
Vale, com uma condição: a IA não pode ser juiz e réu na mesma etapa
A evidência sustenta duas coisas bem concretas
Uma, que código bugado no contexto empurra o modelo a gerar teste que confirma o erro e a gerar menos teste capaz de achar o bug (o efeito de desorientação, ISSTA 2026)
Duas, que teste de agente carrega muito mais asserção ambígua ou não classificada, 11,58% contra 1,46% do humano, e que aparece risco de Assertion Roulette
E tem uma coisa que a evidência NÃO sustenta, apesar de soar bem: que mais teste gerado por agente resolve mais bug
No SWE-bench Verified, agentes que resolvem escrevem teste praticamente na mesma taxa dos que falham, e mexer nesse volume pra cima ou pra baixo não mudou a taxa de resolução de forma estatisticamente significativa
Então TDD com IA não é sobre produzir mais teste
É sobre proteger a INDEPENDÊNCIA do teste
O que muda de fato é onde mora a disciplina: ela saiu do editor e foi pra ordem do prompt
Conclusão
O TDD sempre foi sobre ordem, e a IA não mudou isso, ela só deixou muito mais fácil e mais barato quebrar a ordem sem perceber
O teste que sai junto com o código na mesma resposta não é verificação, é autoelogio
Próximo passo concreto, pro próximo bug que tu pegar: escreve o comportamento esperado em pares entrada/saída ANTES de mostrar qualquer código pra IA, pede só o teste, e exige ver o teste falhar
E guarda essa: se o teste passar de primeira, ele é suspeito, não é conquista
até o próximo post! =)
Perguntas frequentes
Dá pra usar o plan mode do Claude Code pra garantir a etapa Red do TDD com IA?
Dá sim. O Claude Code tem um modo de planejamento em que ele lê, analisa e propõe um plano sem editar arquivo nenhum, e o Shift+Tab alterna entre Default, Auto-accept edits e Plan mode. Enquanto tu está em plan mode as edições ficam bloqueadas até aprovar o plano, então dá pra pedir os testes, revisar a proposta e só liberar a implementação depois de confirmar que eles falharam.
Como impedir que o Claude Code escreva a implementação antes do teste falhar?
Além de pedir explicitamente pra IA não implementar nessa etapa, como manda o fluxo oficial de TDD do Claude Code, dá pra reforçar isso nas permissões do settings.json, que é o passo 7 do fluxo do post. As regras allow, ask e deny são avaliadas nessa ordem de precedência, com deny prevalecendo sobre allow e a primeira correspondência decidindo, então uma regra deny transforma o pedido do prompt em barreira de verdade.
Subagentes do Claude Code servem pra separar quem escreve o teste de quem escreve o código?
O Claude Code suporta subagentes com contexto próprio, gerenciados pelo comando /agents e definidos em Markdown com frontmatter YAML (campos obrigatórios name e description), guardados em .claude/agents/ no projeto ou em ~/.claude/agents/ pro usuário. Dá pra montar um subagente focado só em escrever teste a partir da especificação e outro focado só na implementação, cada um com seu próprio contexto na conversa.
Hooks tipo PostToolUse rodam os testes automaticamente depois que a IA edita o código?
Sim, e é o passo 8 do fluxo do post. O Claude Code tem o evento PostToolUse, configurado no settings.json com matcher de ferramenta, que dispara depois que uma ferramenta (incluindo as de edição de arquivo) é executada com sucesso. Dá pra usar esse hook pra rodar lint, formatação ou a suíte de testes automaticamente assim que o código muda, em vez de aceitar "os testes passaram" como texto na conversa.
Teste escrito por agente de IA é pior que teste escrito por humano?
Não é bem pior, é diferente. Um estudo com 204.673 artefatos de teste (24.941 humanos e 179.732 de agente) achou asserção forte em 88,1% dos testes humanos contra 85,37% dos de agente, praticamente empatado, e o agente até supera em variedade de checagem de borda (0,62 contra 0,32) e teste de null-safety (13,40% contra 8,3%). O buraco real está em asserção ambígua ou não classificada: 1,46% no humano contra 11,58% no agente.
Escrever mais testes com IA aumenta a chance de resolver o bug?
Segundo um estudo com 6 LLMs no SWE-bench Verified, não. Agentes que resolvem o bug escrevem testes praticamente na mesma taxa dos que falham, e experimentos controlados aumentando ou diminuindo a escrita de testes não mudaram a taxa de resolução de forma estatisticamente significativa. O próprio estudo notou que os agentes tendem a usar print revelando valor em vez de asserção formal, o que ajuda a entender por que volume de teste sozinho não é garantia de nada.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
As diferenças de var, let e const
Como fazer redirecionamento com PHP
Neste artigo você vai aprender a como fazer redirecionamento com PHP, utilizaremos abordagens fáceis de entender e de aplicar Fala programador(a), beleza? Bora aprender mais […]
ChatGPT: o que é, como usar, dicas e como acessar login
ChatGPT é uma ferramenta de processamento de linguagem natural (NLP) baseada na arquitetura GPT-3.5, desenvolvida pela OpenAI. Sua criação representa um marco significativo no campo […]
