Como pedir testes ao Claude Code sem receber teste que só confirma o que o código já faz

fluxo de testes com Claude Code seguindo TDD antes de escrever o código
Resposta rápida

Testes com Claude Code só valem alguma coisa quando nascem do comportamento esperado, e não da implementação que já está escrita. A documentação oficial recomenda pedir testes a partir de pares de entrada e saída, declarar explicitamente que é TDD (pra ele não criar mock implementation de algo inexistente), rodar a suíte e confirmar a FALHA antes de escrever qualquer implementação, commitar os testes e só então pedir o código instruindo a não modificar os testes. Pra auditar o resultado, cobertura de linha não serve como prova: teste de mutação mostra o que a suíte realmente detecta.

Teste que passa de primeira e nunca foi visto falhando não é teste, é eco do código

Ele foi escrito olhando a implementação que já estava ali, então só repete o que o código faz, com outras palavras e um expect no fim

Se tu usa Claude Code no dia a dia a cena é conhecida: você pede teste, ele enche a pasta de arquivo, roda, tudo verde, sensação de dever cumprido… e o bug continua vivo esperando o deploy 🙂

Aqui eu vou pelo lado prático de testes com Claude Code: COMO formular o pedido pra nascer um teste que consegue falhar, e como olhar pro que veio e perceber que aquilo não prova nada

O que você precisa antes de pedir o teste

Nada de PC da Nasa, é coisa simples, mas sem isso o resto não funciona

  • Um runner de teste que você mesmo consiga rodar, no terminal, sem depender do agente pra saber se passou ou não
  • Um comportamento definido pra garantir: uma regra de negócio, um caso de borda, uma condição específica. Se você não sabe o que quer provar, ele também não vai saber
  • Um CLAUDE.md na raiz do projeto, que o Claude Code lê no início de toda sessão. É ali que moram as instruções permanentes: convenções, comandos de build e regra do tipo "sempre faça X"
Domine o Claude Code do básico ao avançado
Pré-inscrição Formação Claude Code

Domine o Claude Code do básico ao avançado

Você vai aprender a criar sistemas completos com Claude Code, sem precisar ser programador. Inscreva-se para ter acesso a um desconto de lançamento e bônus especiais!

E tem um detalhe que muita gente não sabe: são DOIS sistemas de memória carregados no começo de cada conversa

Os arquivos CLAUDE.md, que você escreve na mão, e a Auto memory, que é o próprio Claude anotando o que aprendeu com as suas correções

Pra ver onde tudo isso vive, roda /memory dentro do Claude Code: ele lista os locais dos arquivos de memória (CLAUDE.md, CLAUDE.local.md) nos escopos de usuário e de projeto, e deixa ligar ou desligar a Auto memory

Vale a leitura de o que dá pra delegar em testes antes de sair pedindo suíte inteira, porque parte do trabalho continua sendo sua

Passo a passo: pedido de teste que consegue falhar

O fluxo abaixo segue as boas práticas oficiais do Claude Code, que tratam TDD como um caminho bem definido pro agente

  1. Descreva o comportamento em pares de entrada e saída, não aponte o arquivo

A recomendação oficial é pedir testes baseados em pares de entrada e saída esperados, ou seja, partindo do comportamento

A própria documentação contrasta o pedido vago com o pedido específico:

# vago
add tests for foo.py

# específico
write a test for foo.py covering the edge case where the user is
logged out. avoid mocks.

Sente a diferença? O primeiro só diz ONDE mexer, e aí ele lê a implementação e devolve o espelho dela

O segundo diz QUAL condição precisa ser provada, e ainda corta o atalho preguiçoso do mock

Erro comum deste passo: nomear o arquivo e achar que já especificou. Arquivo é endereço, não é comportamento

  1. Diga explicitamente que você está fazendo TDD

Parece redundante, mas não é

Ser explícito sobre TDD evita que ele crie mock implementations de funcionalidade que ainda nem existe na base de código

Estamos fazendo TDD. A funcionalidade ainda NÃO existe no projeto.
Escreva só os testes, baseados nestes pares de entrada e saída.

Erro comum deste passo: deixar implícito. Sem o aviso, ele tende a inventar uma implementação de mentira só pra sua suíte ficar verde, e verde falso é pior que vermelho honesto

  1. Mande rodar os testes e confirmar que eles FALHAM

Esse é o passo que separa teste de enfeite

O fluxo oficial manda rodar, confirmar a falha e instruir explicitamente a não escrever código de implementação ainda

Rode os testes e confirme que eles falham.
Não escreva nenhum código de implementação nesta etapa.

Se você nunca viu o teste vermelho, você não sabe se ele é capaz de ficar vermelho, beleza?

E tem um cuidado extra aqui: garantir que ele rode os testes de verdade em vez de só afirmar que rodou

Erro comum deste passo: aceitar o "os testes falham como esperado" no texto da resposta, sem a saída real do runner na tela

  1. Commite os testes antes de implementar

Quando você estiver satisfeito com os testes, commita

O commit acontece ANTES da fase de implementação, e isso não é frescura de processo: é o congelamento da régua

git add tests/
git commit -m "testes do comportamento X (ainda falhando)"

Erro comum deste passo: seguir direto pra implementação com os testes soltos na árvore. Aí depois, quando algo é ajustado, ninguém consegue mais dizer o que era régua original e o que foi remendo

  1. Peça o código que passa, instruindo a NÃO modificar os testes

Agora sim libera a implementação

Agora escreva o código que faz esses testes passarem.
Não modifique os testes.

A documentação avisa que normalmente leva algumas iterações: escrever código, rodar teste, ajustar, rodar de novo

Isso é o processo funcionando, não é ele errando

Erro comum deste passo: esquecer a trava. Sem ela, existe o caminho fácil de afrouxar a asserção até o teste passar, e a régua vira borracha

Como perceber que o teste gerado não prova nada

Tem sintoma visível, dá pra bater o olho e desconfiar

Sintoma O que ele denuncia
O teste nunca foi visto falhando Pulou a etapa de confirmar a falha, ninguém sabe se ele detecta algo
Chama o método e não afirma nada sobre a saída Executa linha, não verifica comportamento
Cobertura de linha alta usada como prova de qualidade Métrica errada pra pergunta certa
Mock cobrindo justamente a funcionalidade sob teste O que está sendo testado é o mock, não o seu código

A cobertura merece um parágrafo só dela

Cobertura de linha mede quais linhas os testes EXECUTAM, não se os testes são capazes de detectar um defeito

Um teste que chama o método e não verifica nada leva a cobertura a 100% sem detectar absolutamente nada. Ou seja: 100% verde e zero garantia 😛

E como eu descubro se a suíte detecta bug de verdade?

Com teste de mutação

A ideia é simples e meio sádica: a ferramenta introduz pequenas alterações automáticas no seu código (os mutantes) e roda a suíte contra cada uma delas

Se os testes falham, o mutante foi eliminado, ótimo, sua suíte percebeu a mudança

Se os testes passam, o mutante SOBREVIVEU, e isso significa que a linha foi executada mas nenhum teste afirma nada significativo sobre a saída

Existe ferramenta por linguagem:

Linguagem Ferramenta
JavaScript e TypeScript Stryker
Java PIT (PITest)
Python mutmut

E a prevenção? Vira regra permanente

Como o CLAUDE.md é lido no início de toda sessão, as réguas que você repete toda hora no chat cabem melhor lá dentro: pedido de teste sempre em pares de entrada e saída, confirmar a falha antes de implementar, não modificar teste na fase de implementação

Assim você para de negociar o mesmo ponto em cada conversa nova

Como formular o pedido em três situações comuns

O método é sempre o mesmo, o que muda é de onde nasce o comportamento

Correção de bug:

O pedido nasce do caso que reproduz a falha, não do arquivo onde você acha que ela mora

Descreve a entrada que quebra e a saída que deveria acontecer, e exige o vermelho ANTES do fix

Estamos fazendo TDD. Com a entrada <X>, a função devolve <Y>,
mas deveria devolver <Z>. Escreva o teste desse par de entrada e saída,
rode e confirme que ele falha. Não corrija o código ainda.

Teste de correção de bug que já nasce verde é praticamente inútil: ele nem viu o defeito

Caso de borda específico:

Aqui o exemplo oficial é o melhor molde que existe: nomear a condição e cortar o mock

Em vez de "cobre os casos de erro", você diz qual erro, em qual condição, com qual saída esperada

Estamos fazendo TDD. Escreva um teste para <arquivo> cobrindo o caso
de borda em que <condição específica>, esperando <saída>. Evite mocks.
Rode e confirme que ele falha antes de qualquer implementação.

Quanto mais a condição estiver escrita na primeira linha do pedido, menos ele precisa adivinhar lendo a implementação

Refatoração:

Esse é o caso onde teste colado na implementação dói mais

Se o teste espelha a estrutura interna, ele quebra na primeira troca de implementação e você acaba "consertando teste" o dia inteiro, sem ter alterado nenhum comportamento

Então o pedido aqui não nasce de comportamento novo, nasce do comportamento que JÁ existe e precisa continuar igual depois da troca

Amarra tudo no observável: mesma entrada, mesma saída, independente de como está feito por dentro

Estamos fazendo TDD. Escreva testes que descrevam o comportamento
observável atual (entradas e saídas), sem depender da estrutura
interna nem de mocks das dependências que serão trocadas.

Aí você roda essa suíte ANTES de mexer em qualquer linha, commita ela verde, e só então libera a refatoração instruindo a não modificar os testes

Se algum teste ficar vermelho durante a troca, não é o teste que está chato: é comportamento mudando sem você ter pedido, que é exatamente o que a refatoração não podia fazer 🙂

Conclusão

A régua cabe numa frase: teste que nunca falhou não é teste, é eco do código

E quando o pedido parte do comportamento, em pares de entrada e saída, com TDD declarado e a falha confirmada antes de qualquer implementação, o agente para de descrever o que já existe e passa a provar o que você quer garantir

Próximo passo, hoje mesmo: escolhe UM comportamento do teu projeto, escreve o pedido em pares de entrada e saída, exige ver o vermelho antes de liberar a implementação

Se ainda sobrar dúvida sobre a suíte que já está lá, roda um teste de mutação e deixa os mutantes sobreviventes te contarem onde ninguém está afirmando nada

até o próximo post! 😀

Perguntas frequentes

Como pedir teste ao Claude Code sem ele só copiar a implementação?

Descreva o comportamento em pares de entrada e saída esperados, não aponte o arquivo e peça "testes". A recomendação oficial é exatamente essa: partir do que a função deve fazer, não do que ela já faz. Quando você só nomeia o arquivo, ele lê a implementação pronta e devolve um espelho dela em forma de teste.

Por que preciso avisar que estou fazendo TDD antes de pedir os testes?

Porque sem esse aviso explícito o Claude Code tende a criar mock implementations para cobrir funcionalidade que ainda nem existe no código. Declarar TDD deixa claro que a implementação vem depois, não antes. É um dos passos da documentação oficial de boas práticas do Claude Code.

Preciso rodar os testes eu mesmo ou posso confiar no que o agente diz?

Rode você mesmo, no seu runner de teste, sem depender só da resposta do agente. O fluxo oficial manda confirmar que os testes falham antes de qualquer código de implementação, e essa confirmação precisa ser a saída real do runner na tela, não uma frase afirmando que falhou.

Cobertura de código alta é prova de que os testes com Claude Code são bons?

Não. Cobertura de linha mede quais linhas os testes executam, não se eles são capazes de detectar um defeito. Um teste que chama o método sem afirmar nada sobre a saída chega a 100% de cobertura sem detectar absolutamente nada.

Em que momento devo commitar os testes gerados pelo Claude Code?

Assim que estiver satisfeito com eles, e antes de pedir a implementação. A documentação oficial orienta esse commit prévio justamente para congelar a régua: depois, quando algo for ajustado, dá para saber o que era teste original e o que foi remendo.

Que ferramentas existem para checar se a suíte de testes detecta bug de verdade?

Teste de mutação, que introduz pequenas alterações automáticas no código (mutantes) e roda a suíte contra cada uma. Se os testes falham o mutante é eliminado, se passam o mutante sobreviveu e sobrou uma lacuna. Por linguagem existem Stryker para JavaScript e TypeScript, PIT (PITest) para Java e mutmut para Python.



Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares