🧪 Por que testar cada primitivo isolado
Quando primitivos são compostos sem teste individual, bugs em componentes específicos ficam ocultos pelo comportamento emergente da composição. Testar cada primitivo em isolamento significa: se algo falha, você sabe exatamente o que falhou.
Primitivo 1: Escrita atômica
Teste: escrever estado, matar processo no meio, confirmar que arquivo não está corrompido
Primitivo 2: Lockfile
Teste: iniciar duas instâncias simultâneas, confirmar que apenas uma executa
Primitivo 3: Fail-open
Teste: forçar erro no plugin, confirmar que Claude Code continua operando normalmente
🔬 Platform tests
Platform tests verificam as capacidades do ambiente de execução antes de qualquer build. São executados uma vez, antes do primeiro prompt, para confirmar que o ambiente suporta o que o plugin vai fazer.
Checklist de platform tests
#!/usr/bin/env bash
# platform_test.sh
echo "=== Platform Tests ==="
# Versão do bash
bash_version=$(bash --version | head -1)
echo "Bash: $bash_version"
# jq disponível (para JSON)
jq --version > /dev/null 2>&1 && echo "jq: OK" || echo "jq: MISSING"
# mkdir atômica (lockfile)
mkdir /tmp/test_atomic_lock 2>/dev/null && \
rmdir /tmp/test_atomic_lock && \
echo "Atomic mkdir: OK"
# mv atômico (write-then-rename)
echo "test" > /tmp/test_atomic.tmp && \
mv /tmp/test_atomic.tmp /tmp/test_atomic && \
rm /tmp/test_atomic && \
echo "Atomic mv: OK"
echo "=== Done ==="
💨 Smoke tests
Smoke tests são o mínimo necessário para confirmar que uma camada não está obviamente quebrada. Rápidos, diretos, cobrindo apenas o happy path — não edge cases. São o gate mínimo entre prompts.
Smoke test por camada
Scaffold
Todos os arquivos esperados existem. O hook pode ser invocado sem erro.
Estado
Inicializar estado, ler estado, fazer transição — sem erros.
Lógica
Executar o fluxo principal de ponta a ponta com input mínimo.
Segurança
Forçar falha em cada caminho de erro e confirmar fail-open.
🎭 E2E sintético
E2E sintético simula o fluxo real do sistema com dependências substituídas por stubs controlados. Cobertura de fluxo completo, velocidade de teste unitário, sem dependência de serviços externos.
Estrutura de E2E sintético
# e2e_synthetic.sh
# Simula uma sessão completa sem Claude Code real
# Setup: estado inicial
echo '{"phase":"idle","version":1}' > /tmp/test_state.json
# Simula trigger do hook PreToolUse
./hooks/pre_tool_use.sh '{"tool":"Write"}' && echo "PreToolUse: OK"
# Simula Stop Hook fase 1 (planning)
./hooks/stop.sh '{"session_id":"test"}' && echo "Stop phase 1: OK"
# Simula Stop Hook fase 2 (running)
./hooks/stop.sh '{"session_id":"test"}' && echo "Stop phase 2: OK"
# Verificar estado final
phase=$(jq -r '.phase' /tmp/test_state.json)
[ "$phase" = "done" ] && echo "E2E: PASS" || echo "E2E: FAIL"
# Cleanup
rm /tmp/test_state.json
📊 O que fazer quando um teste falha no meio da sequência
Um teste que falha no prompt N não significa necessariamente que o prompt N está errado. O protocolo de diagnóstico identifica a camada real da falha antes de qualquer ação.
Replicar em isolamento
Isolar o comportamento que falhou. Remover todas as dependências externas e testar o componente específico de forma independente.
Bisect por camada
Testar as camadas anteriores individualmente. Se o smoke test da camada N-1 falha, o problema está nela — não no prompt atual.
Regredir apenas a camada com falha
Identificada a camada, regredir apenas ela. Preservar tudo que foi verificado. Re-executar o prompt com diagnóstico explícito no contexto.
🔄 Regressão
Regressão é re-executar os testes de todas as camadas anteriores após cada novo prompt. Garante que a nova camada não quebrou comportamentos já verificados — um risco real quando o modelo resolve a tarefa de uma forma que invalida suposições anteriores.
Suite de regressão mínima
#!/usr/bin/env bash
# regression.sh — executar após cada prompt
echo "=== Regression Suite ==="
# Camada 1: Scaffold
[ -f "hooks/pre_tool_use.sh" ] && echo "Scaffold: OK" || echo "Scaffold: FAIL"
[ -f "hooks/stop.sh" ] && echo "Stop hook: OK" || echo "Stop hook: FAIL"
# Camada 2: Estado
./test/state_init_test.sh && echo "State init: OK" || echo "State init: FAIL"
./test/state_transition_test.sh && echo "State transition: OK" || echo "State: FAIL"
# Camada 3: Primitivas de segurança
./test/fail_open_test.sh && echo "Fail-open: OK" || echo "Fail-open: FAIL"
./test/atomic_write_test.sh && echo "Atomic write: OK" || echo "Atomic write: FAIL"
echo "=== Done ==="
💡 Regressão como hábito
A suite de regressão deve ser executável em menos de 2 minutos para se tornar hábito. Se levar mais, ela será pulada sob pressão. Mantenha os testes rápidos — cobertura de intenção, não cobertura de linha.
✅ Resumo do Módulo 3.5
Próximo Módulo:
3.6 — Do Zero ao SPEC: Seu Próximo Projeto