Capítulo 14 — Testes e gates mecânicos
“Parece certo” não é uma propriedade verificável
Section titled ““Parece certo” não é uma propriedade verificável”Depois de definir a arquitetura de evidência, precisamos tornar parte dela executável.
A pergunta deste capítulo é:
como transformar expectativas em gates mecânicos?
Um gate mecânico é uma verificação que pode ser executada novamente e produzir um resultado observável contra uma condição explícita.
Exemplos:
- teste unitário;
- teste de integração;
- type check;
- lint;
- schema validation;
- contract check;
- security scan;
- migration dry run;
- benchmark;
- eval.
O objetivo não é maximizar número de checks.
É encontrar o check mais barato que seja confiável o suficiente para a propriedade em questão.
Isso é método deste livro.
TDD como mecanismo de feedback
Section titled “TDD como mecanismo de feedback”Beck organiza TDD no ciclo Red → Green → Refactor, usando testes automatizados como feedback rápido para orientar implementação e design. 1
O valor central para engenharia agêntica não é ritualizar “teste primeiro”.
É reduzir a distância entre:
- hipótese;
- implementação;
- verificação;
- correção.
Quanto menor esse ciclo, menor o espaço para grandes desvios silenciosos.
Especifique uma propriedade em forma executável.
Exemplo:
given paid_orderwhen retry_paymentthen charge_count == 1O teste falhando demonstra que a propriedade ainda não está satisfeita.
Implemente o mínimo necessário para satisfazer a propriedade.
O objetivo não é perfeição arquitetural imediata.
É estabelecer um novo ponto de feedback confiável.
Refactor
Section titled “Refactor”Com o comportamento protegido, reorganize estrutura.
Fowler enfatiza passos pequenos e teste após cada mudança como forma segura de refactoring. 2
Para agentes, esse ponto é crucial: capacidade de gerar uma transformação grande rapidamente não torna a transformação menos arriscada.
TDD não substitui Spec
Section titled “TDD não substitui Spec”Um teste pode ser perfeitamente escrito para a regra errada.
Por isso, o fluxo completo é:
Spec ↓acceptance property ↓test/check ↓implementation ↓resultSem Spec, TDD pode apenas acelerar a implementação de uma interpretação incorreta.
Characterization tests
Section titled “Characterization tests”Em sistemas existentes, muitas vezes não começamos sabendo o comportamento correto.
Começamos sabendo apenas o comportamento observado.
Characterization tests registram esse estado antes da mudança.
Eles respondem:
“o que o sistema faz agora?”
Depois classificamos esse comportamento como:
- intencional;
- bug conhecido;
- desconhecido;
- dependência externa;
- candidato a remoção.
Characterization test não transforma comportamento legado em requisito eterno.
Ele cria visibilidade para mudança.
Unit test
Section titled “Unit test”Unit test verifica uma unidade pequena em isolamento relativo.
Bom para:
- regras locais;
- edge cases;
- funções puras;
- invariants internos.
Vantagens:
- rápido;
- barato;
- diagnóstico preciso.
Limitação:
- pode passar enquanto integração falha.
Integration test
Section titled “Integration test”Integration test verifica colaboração entre componentes.
Bom para:
- banco;
- filas;
- APIs;
- storage;
- adapters;
- schemas.
É particularmente importante quando o risco está na boundary.
System / end-to-end test
Section titled “System / end-to-end test”Verifica um fluxo completo.
Bom para provar:
- journey crítica;
- integração real de várias camadas;
- comportamento externo observável.
É mais caro e normalmente mais lento.
Por isso, não deveria ser a única forma de feedback.
Test pyramid como heurística, não dogma
Section titled “Test pyramid como heurística, não dogma”O método deste livro não exige uma pirâmide fixa.
A ideia útil é manter:
- muitos checks baratos perto da lógica;
- menos checks caros perto das integrações completas.
A distribuição deve seguir risco e custo de diagnóstico.
Static checks
Section titled “Static checks”Nem toda propriedade precisa executar o sistema.
Static checks podem detectar:
- erro de tipo;
- import inválido;
- dead code;
- regra de estilo;
- vulnerabilidade conhecida;
- API misuse;
- policy violation.
Exemplos:
- compiler;
- type checker;
- linter;
- SAST;
- dependency scanner.
A vantagem é custo baixo e repetibilidade.
Necessários, mas insuficientes
Section titled “Necessários, mas insuficientes”Tantithamthavorn observa que test suites, linters, type checkers e security scanners são uma primeira linha de verificação, mas podem deixar passar violações da especificação que não foram codificadas nos checks. 3
Esse é o ponto central:
check verde prova apenas aquilo que o check consegue observar.
Contracts
Section titled “Contracts”Contracts tornam boundaries verificáveis.
Podem assumir forma de:
- OpenAPI;
- JSON Schema;
- protobuf;
- database constraints;
- event schemas;
- type contracts;
- consumer-driven contracts.
Eles ajudam a detectar incompatibilidade antes de runtime.
Schema gate
Section titled “Schema gate”Um schema gate pode perguntar:
- campo obrigatório foi removido?
- tipo mudou?
- enum ficou incompatível?
- migration destrói coluna usada?
- evento quebrou consumidor?
Essas perguntas são mecanizáveis.
Security checks
Section titled “Security checks”Security gate pode incluir:
- secret scanning;
- dependency vulnerabilities;
- SAST;
- permission diff;
- container scan;
- IaC policy check;
- auth regression tests.
Mas security check também pode virar teatro se não corresponder ao threat model.
Quando o comportamento do produto inclui componentes probabilísticos, testes binários tradicionais podem não bastar.
Evals podem medir:
- factuality;
- format adherence;
- refusal behavior;
- retrieval quality;
- latency;
- tool-selection quality;
- success rate em cenários.
No método deste livro, eval entra quando a própria propriedade é probabilística ou estatística.
Não usamos eval para substituir teste determinístico quando a propriedade é determinística.
Deterministic property, deterministic check
Section titled “Deterministic property, deterministic check”Exemplo:
“JSON precisa obedecer ao schema.”
Use schema validator.
Não use LLM judge.
Probabilistic property, statistical check
Section titled “Probabilistic property, statistical check”Exemplo:
“o assistente deve recuperar a política correta em pelo menos 95% dos casos do benchmark.”
Aqui um conjunto de casos e métricas faz sentido.
Cheapest reliable verification
Section titled “Cheapest reliable verification”O gate deste capítulo é:
cada acceptance property deve ter a verificação confiável mais barata disponível.
Exemplo:
| Property | Check preferido |
|---|---|
| função soma corretamente | unit test |
| contrato API não quebrou | schema/contract check |
| migration aplica | migration test |
| botão aparece corretamente | visual/browser test |
| secret não foi commitado | secret scan |
| fluxo checkout funciona | integration/E2E |
| resposta probabilística mantém qualidade | eval |
Isso evita checks caros onde um mecanismo simples resolve.
Mechanical Gate Checklist
Section titled “Mechanical Gate Checklist”Artefato operacional deste capítulo:
Property
Section titled “Property”O que precisa ser verdadeiro?
Cheapest reliable check
Section titled “Cheapest reliable check”Qual mecanismo observa isso com menor custo?
Failure signal
Section titled “Failure signal”Como o check falha?
Policy
Section titled “Policy”Falha bloqueia, alerta ou escala?
Qual parte do sistema cobre?
Independence
Section titled “Independence”Quem gerou o check?
Reproducibility
Section titled “Reproducibility”Pode ser executado novamente?
Evidence pointer
Section titled “Evidence pointer”Onde o resultado fica registrado?
Falso gate #1 — check que nunca bloqueia
Section titled “Falso gate #1 — check que nunca bloqueia”Se falhar e nada acontece, não é gate.
É telemetria decorativa.
Um gate precisa ter consequência definida:
- block;
- warn;
- escalate;
- require exception.
Falso gate #2 — teste impossível de falhar
Section titled “Falso gate #2 — teste impossível de falhar”Exemplos:
- assertion trivial;
- mock que retorna exatamente o esperado;
- snapshot sempre atualizado automaticamente;
- teste que só confirma status 200 sem conteúdo.
Esse check aumenta contagem sem aumentar confiança.
Falso gate #3 — cobertura como objetivo isolado
Section titled “Falso gate #3 — cobertura como objetivo isolado”Coverage mede execução de linhas/branches.
Não mede qualidade da assertion.
100% de coverage pode coexistir com testes inúteis.
Coverage é sinal auxiliar, não prova universal.
Falso gate #4 — mesmo agente escreve código e valida intenção
Section titled “Falso gate #4 — mesmo agente escreve código e valida intenção”O mesmo agente pode produzir implementação e testes coerentes entre si, mas ambos errados em relação à Spec.
Isso não torna os testes inválidos.
Mas reduz independência.
Compensações possíveis:
- acceptance criteria explícitos;
- revisão humana;
- second-agent verification;
- contract independente;
- golden dataset;
- differential test.
Falso gate #5 — suite histórica irrelevante
Section titled “Falso gate #5 — suite histórica irrelevante”Uma suite pode estar verde porque nunca observou o fluxo alterado.
Pergunta essencial:
qual risco desta mudança cada check cobre?
Mutation / challenge mindset
Section titled “Mutation / challenge mindset”Uma forma de avaliar teste é perguntar:
se a implementação estivesse errada desta maneira, o teste falharia?
Não precisamos necessariamente usar mutation testing automatizado em todo projeto.
Mas o raciocínio é útil.
Negative tests
Section titled “Negative tests”Muitos sistemas testam apenas happy path.
Gates fortes incluem:
- input inválido;
- boundary values;
- timeout;
- duplicate request;
- permission denied;
- partial failure;
- retry;
- malformed payload.
Test data
Section titled “Test data”Dados de teste também fazem parte do gate.
Um teste realista precisa representar:
- formatos;
- ranges;
- edge cases;
- relacionamentos;
- constraints.
Fixture irreal pode produzir confiança falsa.
Flaky test
Section titled “Flaky test”Gate instável destrói confiança.
Quando um teste falha aleatoriamente, times aprendem a rerodar até verde.
Isso transforma o gate em ritual.
Flakiness deve ser tratada como defeito operacional do sistema de verificação.
Time budget
Section titled “Time budget”Gate lento demais incentiva bypass.
Por isso, mantenha camadas:
- fast local checks;
- CI checks;
- expensive pre-merge checks;
- runtime validation.
A velocidade do feedback é parte da qualidade do gate.
Local vs CI
Section titled “Local vs CI”Checks críticos devem ser reproduzíveis fora da máquina do autor.
Idealmente:
local command =CI commandDiferença excessiva entre local e CI aumenta surpresa.
Gate composition
Section titled “Gate composition”Nenhum check individual precisa provar tudo.
Confiança pode ser composta:
unit+ type+ contract+ integration+ security+ revisãoO conjunto precisa cobrir o risco relevante.
Gate ordering
Section titled “Gate ordering”Execute checks baratos primeiro.
Exemplo:
format ↓lint ↓type ↓unit ↓integration ↓security ↓E2EIsso reduz custo desperdiçado.
Small-batch verification
Section titled “Small-batch verification”Mudanças pequenas melhoram diagnóstico.
Fowler recomenda refactoring em passos pequenos com teste após cada passo. 2
Em fluxo agêntico, isso também reduz o volume que precisa ser explicado em um único revisão.
Agent-generated tests
Section titled “Agent-generated tests”Agentes são úteis para:
- gerar casos;
- expandir edge cases;
- construir fixtures;
- criar property tests;
- traduzir acceptance criteria.
Mas os testes precisam continuar vinculados à Spec.
O fato de terem sido gerados rapidamente não altera o gate de qualidade.
Review consultivo continua necessário
Section titled “Review consultivo continua necessário”McEntire distingue gates mecânicos de revisão consultiva. 4
Mechanical gates respondem propriedades formalizáveis.
Review humano ou consultivo responde:
- trade-offs;
- arquitetura;
- adequação ao domínio;
- risco;
- legibilidade;
- decisão de exceção.
Não devemos pedir a um linter que resolva julgamento arquitetural.
Gate registry
Section titled “Gate registry”Como método deste livro, podemos manter um registro:
| Gate | Property | Command | Scope | Policy | Owner |
|---|---|---|---|---|---|
| unit | local correctness | npm test | package | block | team |
| types | type consistency | tsc –noEmit | repo | block | team |
| contracts | API compatibility | contract-check | API | block | platform |
| secrets | no leaked secret | secret-scan | repo | block | security |
| eval | response quality | eval run | AI feature | warn/block | product |
Isso transforma verificação em infraestrutura explícita.
Gate drift
Section titled “Gate drift”Checks também envelhecem.
Podem deixar de refletir:
- arquitetura;
- risco;
- dependências;
- Spec;
- threat model.
Gates precisam de manutenção.
Quando remover um gate
Section titled “Quando remover um gate”Remova ou substitua quando:
- não observa propriedade relevante;
- é redundante sem valor;
- está permanentemente flaky;
- custo excede benefício;
- a arquitetura mudou.
Não preserve check só porque “sempre esteve no CI”.
Do gate ao revisão
Section titled “Do gate ao revisão”Mechanical gates transformam parte das obligations do capítulo anterior em checks repetíveis.
Quando isso funciona, o revisor deixa de gastar atenção confirmando propriedades que já possuem verificação confiável e pode focar em intenção, risco, trade-offs, scope e exceptions.
Essa é a transição central:
Evidence Architecture define o que precisa ser demonstrado. Gates automatizam o que pode ser demonstrado mecanicamente. Review decide o que ainda exige julgamento.
O próximo capítulo trata dessa decisão e de como preservá-la em Git e memória operacional.
Fronteira de confiança
Section titled “Fronteira de confiança”Um check é uma trust boundary entre implementação e aceitação. O resultado só vale dentro do escopo que o check observa; mocks, fixtures, environment e toolchain também fazem parte dessa boundary.
Evidência exigida
Section titled “Evidência exigida”Cada gate deve declarar propriedade, comando/mecanismo, scope, failure signal, política e evidência pointer. Um check verde sem propriedade explícita não deve ser tratado como prova suficiente.
Rollback e recuperação
Section titled “Rollback e recuperação”Mudanças em gates precisam ser reversíveis e auditáveis. Desabilitar, afrouxar ou bypassar um gate crítico altera a política de risco do sistema e deve deixar registro explícito.
Proveniência das fontes
Section titled “Proveniência das fontes”Rastreabilidade deste capítulo:
- CLM-004 e CLM-050 — Beck, ciclo TDD Red → Green → Refactor;
- CLM-051 — Fowler, refactoring seguro em passos pequenos com teste frequente;
- CLM-052 — Tantithamthavorn, automated checks como primeira linha necessária, mas insuficiente;
- CLM-008 — McEntire, gates mecânicos versus revisão consultivo.
Mechanical Gate Checklist, cheapest reliable verification, Gate Registry, gate ordering e taxonomy de falsos gates são método deste livro.
O comparável de Nissl permanece fonte limitada e não foi usado como autoridade factual.
Fontes de acesso limitado não foram usadas como autoridade factual neste capítulo.
Recursos complementares
Section titled “Recursos complementares”Recursos relacionados:
- Mechanical Gate Checklist;
- Gate Registry template;
- false-gate audit;
- TDD workflow card;
- characterization test checklist;
- eval selection guide;
- futura visualização PCC de gate coverage por acceptance property.
Living Book Expanded · capítulo executável
Testes e gates mecânicos: abrir Gate Lab. A camada expandida preserva o texto estável e mantém repo/arquivo/commit e What changed? separados do manuscrito canônico.
Footnotes
Section titled “Footnotes”-
Kent Beck, Test-Driven Development: By Example (2002), Preface / Red-Green-Refactor, pp. 1–3. Rastreabilidade interna: CLM-050. ↩
-
Martin Fowler, Refactoring (1999), Chapter 5: Toward a Catalog of Refactorings, p. 85. Rastreabilidade interna: CLM-051. ↩ ↩2
-
Kla Tantithamthavorn, Agentic Software Engineering (2026), Chapter 6: Verify, p. 102. Rastreabilidade interna: CLM-052. ↩
-
Jeremy McEntire, Beyond Code (2026), Chapter 6: Mechanical Gates Over Advisory Review, p. 57. Rastreabilidade interna: CLM-008. ↩