Como pedir ao Claude Code para escrever os testes a partir da especificação?

Pedir ao Claude Code testes a partir da especificação é diferente de pedir "escreve uns testes pra isso": no primeiro caso o oráculo vem do comportamento esperado, no segundo vem do código que já existe. A Anthropic documenta o fluxo: peça os testes com base em pares esperados de entrada e saída, avise que é TDD pra ele não criar mocks de funcionalidade inexistente, mande rodar e confirmar que os testes FALHAM sem escrever implementação, e só então peça o commit dos testes. Depois disso é que entra o código
Fala aí, beleza? Teste escrito depois que o código ficou pronto não testa o código, ele fotografa o código 😅
A cena é sempre a mesma: a feature sai, você pede "escreve uns testes pra isso", a suíte fecha verde e ninguém aprendeu absolutamente nada sobre o comportamento esperado do sistema
A diferença entre os dois pedidos parece boba, mas ela troca a FONTE da verdade
Quando você pede "escreve testes pra isso", a fonte é o código que está ali na frente do agente
Quando você pede os testes a partir da especificação, a fonte passa a ser o comportamento que você combinou que o sistema deveria ter, e aí o teste vira um contrato e não um espelho
A Anthropic descreve esse fluxo direto no material de boas práticas do Claude Code: peça que os testes sejam escritos com base em pares esperados de entrada e saída, ou seja, a partir do comportamento esperado, não do código existente
Bora ver como fazer isso na prática?
O que você precisa antes de começar
Três coisas na mesa, e nenhuma delas é ferramenta nova:
- Uma especificação escrita do comportamento esperado, nem que seja um parágrafo só, desde que tenha entradas e saídas
- Um projeto com suíte de teste que roda por um comando (o teu
npm test,pytest,go test, o que for) - O Claude Code instalado e apontado pra esse projeto
"Mas o que conta como especificação?"
Não precisa ser documento corporativo de 40 páginas, relaxa
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!
Um parágrafo dizendo "dado um CPF com 11 dígitos válidos, retorna true; com dígito verificador errado, retorna false; com string vazia, lança erro de validação" já é uma spec
O que ela precisa ter é comportamento observável: entrou X, sai Y, e nos casos ruins acontece Z
Se a tua "spec" for do tipo "tem que validar direitinho", o agente vai preencher o resto com achismo e o teste vai nascer torto
Duas coisas do Claude Code ajudam MUITO nessa etapa de preparo
A primeira é o plan mode, que apresenta um plano e pede a tua aprovação antes de o Claude sair do modo de planejamento, escrevendo esse plano em um arquivo em disco
Isso é ótimo aqui porque você consegue ler a interpretação que ele fez da spec ANTES de qualquer arquivo de teste existir
A segunda é o CLAUDE.md, que guarda instruções persistentes do projeto e é lido pelo Claude no início de cada sessão
É ali que a regra de TDD para de depender da tua memória, e já volto nisso lá embaixo
Passo a passo: da especificação aos testes que falham
- Transforme a spec em pares de entrada e saída esperados
Esse é o passo que define todo o resto
Antes de pedir qualquer arquivo de teste, peça a TABELA de comportamento:
Leia a especificação em docs/spec-validacao-cpf.md
Não escreva código e não abra os arquivos de implementação ainda
Extraia da spec uma lista de pares esperados de entrada e saída,
incluindo casos de borda e casos de erro
Onde a spec estiver ambígua, liste como pergunta em vez de assumir
O erro comum deste passo: deixar o agente ler o código de implementação antes de montar essa lista
Uma vez que ele viu a função, a lista dele vira descrição do que a função faz, e você perdeu o jogo no primeiro lance
- Diga explicitamente que é TDD
Parece redundante, mas não é: nas boas práticas do Claude Code, a Anthropic recomenda ser explícito de que você está fazendo desenvolvimento guiado por testes, justamente pra que o Claude evite criar implementações fictícias (mocks) de funcionalidades que ainda nem existem no código
Estamos fazendo TDD
A implementação AINDA NÃO EXISTE e isso é esperado
Não crie mocks nem stubs pra simular funcionalidade inexistente:
os testes devem chamar a API real descrita na spec, mesmo que ela
ainda não esteja implementada
O erro comum deste passo: aceitar o mock que ele oferece "pra suíte não quebrar"
Se o teste passa com mock de coisa que não existe, ele está testando o mock, e o mock sempre concorda com você 🙂
- Peça os testes, e SÓ os testes
Agora sim os arquivos:
Escreva os testes a partir da lista de pares de entrada e saída que
você extraiu da spec
Um caso de teste por par, com nome descrevendo o comportamento esperado
Não escreva nenhuma linha de implementação nesta etapa
O erro comum deste passo: pedir "os testes e a implementação" na mesma mensagem
Aí o agente escreve os dois em sequência e ajusta um pelo outro, o que é exatamente o problema que a gente veio resolver
- Mande rodar e confirmar que os testes falham
Esse passo é o coração do ciclo e é o mais pulado
A orientação do mesmo material de boas práticas é clara: mande o Claude rodar os testes e confirmar que eles falham, e dizer explicitamente pra ele não escrever código de implementação nessa etapa costuma ajudar
Rode a suíte e me mostre a saída
Confirme que os novos testes FALHAM e por qual motivo cada um falha
Não escreva código de implementação nesta etapa
O erro comum deste passo: ver teste verde e comemorar
Verde aqui é sintoma ruim! Ou o teste não está exercitando nada, ou ele foi escrito pra bater com algo que já existe
Olhe também o MOTIVO da falha: se todos falham com erro de import, você provou só que o arquivo não existe, não que o comportamento está errado
- Revise os casos contra a spec, não contra o código
Aqui é você trabalhando, não o agente
Pegue a spec do lado esquerdo e a lista de testes do lado direito, e responda duas perguntas: todo comportamento da spec virou pelo menos um teste? Todo teste consegue apontar a linha da spec que o justifica?
Teste sem linha correspondente na spec é candidato a ter saído da cabeça do modelo, e teste da spec que ninguém cobriu é buraco
O erro comum deste passo: revisar abrindo a implementação junto
No instante em que você lê o código, você começa a achar razoável o que ele faz, e é assim que o comportamento real vira "esperado"
- Peça o commit dos testes antes de qualquer implementação
A recomendação nas boas práticas é essa mesma: peça que o Claude faça o commit dos testes quando eles estiverem satisfatórios
Os testes estão bons
Faça o commit APENAS dos arquivos de teste, com mensagem descrevendo
o comportamento especificado
Não inclua nenhum arquivo de implementação neste commit
O erro comum deste passo: deixar tudo num commit gigante no fim
Com os testes commitados antes, qualquer alteração posterior neles aparece no diff, e ajustar o teste pra fazer a implementação passar deixa de ser invisível
É um guardrail (limite) baratinho e resolve mto
Por que o teste gerado depois do código quase sempre passa
O sintoma:
Suíte verde, cobertura bonita no relatório, e o bug estourando em produção numa entrada que qualquer pessoa teria testado à mão
Dá aquela sensação de que a suíte está te enganando… e mais ou menos está mesmo
A causa:
Não é preguiça do modelo, é uma limitação conhecida da geração automática de testes
Um estudo acadêmico sobre geração de oráculos com LLM aponta que abordagens de geração de teste baseadas em LLM tendem a produzir oráculos (as asserções) que capturam o comportamento REAL do programa, e não o comportamento ESPERADO
E isso não é novidade trazida pela IA: a mesma limitação já era conhecida em geradores clássicos como Randoop e EvoSuite
Faz sentido, né? Se a única fonte de verdade disponível é o código, a asserção só pode ser um retrato dele
O mesmo estudo, feito sobre 24 repositórios Java open source, traz outro detalhe prático: os LLMs geram oráculos melhores quando o código tem nomes de variáveis e de testes significativos
Ou seja, nome vago no teste não é só questão de estética, ele degrada o que sai do outro lado
Se você já esbarrou nesse cenário de teste que espelha o código, a raiz é essa, e a correção é trocar a fonte do oráculo
A solução e a prevenção:
Três regras, e elas são chatas de propósito:
- A fonte do oráculo é a spec, nunca o código: se o agente precisou abrir a implementação pra saber o que assertar, o teste já nasceu contaminado
- O teste tem que falhar antes: falha vermelha é a prova de que o teste está de fato exercitando o comportamento e de que ele ainda não existe
- Commit dos testes separado da implementação: assim o teste vira linha de base e não muda de opinião no meio do caminho
Os dois pedidos lado a lado, pra ficar visual:
| "Escreve uns testes pra isso" | Testes a partir da especificação | |
|---|---|---|
| Fonte do oráculo | O código já implementado | O comportamento esperado na spec |
| Primeiro resultado esperado | Suíte verde | Suíte VERMELHA |
| Bug de comportamento errado | Vira teste que protege o bug | Aparece como teste falhando |
| Momento do commit dos testes | Junto com a implementação | Antes da implementação |
Como tornar isso repetível no seu projeto
Fazer o ciclo uma vez é fácil, o difícil é fazer sempre, inclusive na sexta às 18h quando você só quer entregar
Tem quatro caminhos dentro do próprio Claude Code, do mais simples pro mais estruturado
CLAUDE.md: a regra que não depende da tua memória
Arquivos CLAUDE.md guardam instruções persistentes de projeto e são lidos pelo Claude no início de cada sessão
É o lugar natural pra deixar escrito que, naquele repositório, teste vem da spec, mock de funcionalidade inexistente não passa e teste novo precisa falhar antes
Resolve o problema de você ter que repetir o mesmo parágrafo toda santa vez que abre o terminal
Skill: o prompt de TDD guardado em arquivo
Skills no Claude Code são arquivos markdown guardados em .claude/skills/<nome>/SKILL.md, invocáveis por barra e também carregados automaticamente quando são relevantes
Um arquivo em .claude/skills/deploy/SKILL.md gera o comando /deploy, e o equivalente também pode morar em .claude/commands/deploy.md
Traduzindo pro nosso caso: aquele passo a passo inteiro lá de cima vira UM arquivo, e o ciclo passa a ser invocado por um comando em vez de copiar prompt de post de blog 🙂
Resolve a variação: o prompt fica igual pra todo mundo do time
Subagentes: separar quem lê a spec de quem implementa
Subagentes do Claude Code são arquivos markdown guardados em .claude/agents/, e já existem agentes embutidos disponíveis, como Explore, Plan e general-purpose
A sacada aqui é de contexto: o agente que lê a spec e monta os pares de entrada e saída não precisa (nem deveria) estar com a implementação inteira na cabeça
Resolve a contaminação, que é a causa raiz do oráculo espelhado
Hooks: quando você não quer depender da escolha do modelo
Hooks rodam em pontos específicos do ciclo de vida e dão controle determinístico: certas ações SEMPRE acontecem, em vez de depender do modelo decidir executá-las
É a diferença entre "pedi pra ele rodar a suíte" e "a suíte roda"
Resolve o passo esquecido, que no nosso ciclo é quase sempre o passo 4
E se você quiser o pacote completo: Spec Kit
Se a ideia de puxar tudo a partir da especificação te agradou, dá pra ir mais longe com o Spec Kit, um toolkit open source de spec-driven development mantido no repositório oficial github/spec-kit, do GitHub
O fluxo central dele é Spec, Plan, Tasks e Implement, e cada fase produz um artefato em Markdown que alimenta a fase seguinte
Repare que é a mesma lógica do que a gente fez no braço: o documento é que manda, e o código é a última etapa, não a primeira
A inicialização num projeto é pelo specify init via uvx (precisa do uv instalado):
uvx --from git+https://github.com/github/spec-kit.git specify init <PROJECT_NAME>
O comando de init configura os arquivos de comando e a estrutura de diretórios do agente escolhido, e o Claude está entre as integrações suportadas
Um aviso honesto: os comandos de barra que o Spec Kit expõe aparecem em várias listas por aí com formatos diferentes, e eu não confirmei o formato atual na documentação viva, então não vou te ensinar comando que pode estar desatualizado
Roda o init e olha o que ele criou no teu projeto, é o caminho seguro
Conclusão
A própria Anthropic descreve o TDD como fluxo favorito para mudanças que dá pra verificar com teste unitário, de integração ou ponta a ponta
E tem um detalhe que vale colar na parede: sem as etapas de escrever o teste e confirmar que ele falha, o Claude tende a pular direto pra codar a solução
Ou seja, o ciclo não é burocracia, é o que segura o impulso de ir direto pro código
Recapitulando o que importa: a spec vira pares de entrada e saída, você avisa que é TDD pra não ganhar mock de coisa que não existe, pede os testes sem implementação, manda rodar e confirma o VERMELHO, revisa contra a spec e commita os testes antes de qualquer linha de código
Próximo passo concreto: pega a menor tarefa da tua fila hoje, roda o ciclo uma vez inteirinho e faz o commit dos testes antes da implementação
Uma tarefa pequena só, pra sentir o ritmo…
Depois disso fica difícil voltar pro "escreve uns testes pra isso" 😀
até o próximo post!
Perguntas frequentes
Qual a diferença entre pedir para o Claude Code escrever testes e pedir testes a partir da especificação?
Quando você pede só "escreve testes pra isso", a fonte da verdade é o código que já existe, e o teste acaba confirmando o que o código faz. Quando você pede testes a partir da especificação, a fonte passa a ser o comportamento combinado (pares de entrada e saída esperados), e o teste vira um contrato que a implementação ainda precisa cumprir.
Por que o Claude Code cria mocks de funcionalidades que ainda não existem no código?
Porque sem instrução explícita, o modelo tende a simplificar e criar um mock pra fazer a suíte passar, em vez de escrever um teste que chama a API real da spec. Nas boas práticas do Claude Code, a Anthropic recomenda avisar explicitamente que o fluxo é TDD, justamente pra evitar essas implementações fictícias.
O que significa quando os testes passam de primeira ao rodar pela primeira vez?
É sinal ruim, não bom: se a implementação ainda não existe e o teste já passa verde, ou ele não está exercitando nada, ou foi escrito pra bater com algo que já está no código. A orientação é rodar a suíte e confirmar que os testes falham antes de escrever qualquer linha de implementação.
Como o CLAUDE.md ajuda a manter o fluxo de TDD com o Claude Code?
O CLAUDE.md guarda instruções persistentes do projeto e é lido pelo Claude no início de cada sessão. Colocando ali a regra de escrever testes a partir da spec e de não criar mocks, essa regra deixa de depender da tua memória em cada conversa nova.
Preciso usar o Spec Kit para escrever testes a partir da especificação no Claude Code?
Não precisa. Como mostrei na seção sobre ele, o Spec Kit é um toolkit open source de spec-driven development com fluxo Spec, Plan, Tasks e Implement, e é útil quando a especificação já nasce como artefato formal do projeto. Pra um parágrafo de spec e um TDD pontual, o passo a passo direto no Claude Code já resolve.
O plan mode do Claude Code substitui a especificação escrita?
Não substitui, ele complementa. O plan mode apresenta um plano e pede tua aprovação antes de o Claude sair do modo de planejamento, escrevendo esse plano em um arquivo em disco, o que ajuda a conferir a interpretação da spec antes de qualquer teste ser criado.
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 […]
Checklist de segurança n8n VPS pública: guia essencial para proteger sua instalação
Checklist de segurança n8n VPS pública: guia essencial para proteger sua instalação A popularidade da automação de processos com o n8n está em alta, principalmente […]
