Skip to content

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.

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_order
when retry_payment
then charge_count == 1

O 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.

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.

Um teste pode ser perfeitamente escrito para a regra errada.

Por isso, o fluxo completo é:

Spec
↓
acceptance property
↓
test/check
↓
implementation
↓
result

Sem Spec, TDD pode apenas acelerar a implementação de uma interpretação incorreta.

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 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 verifica colaboração entre componentes.

Bom para:

  • banco;
  • filas;
  • APIs;
  • storage;
  • adapters;
  • schemas.

É particularmente importante quando o risco está na boundary.

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.

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.

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.

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 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.

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 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.

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.

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.

Artefato operacional deste capítulo:

O que precisa ser verdadeiro?

Qual mecanismo observa isso com menor custo?

Como o check falha?

Falha bloqueia, alerta ou escala?

Qual parte do sistema cobre?

Quem gerou o check?

Pode ser executado novamente?

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?

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.

Muitos sistemas testam apenas happy path.

Gates fortes incluem:

  • input inválido;
  • boundary values;
  • timeout;
  • duplicate request;
  • permission denied;
  • partial failure;
  • retry;
  • malformed payload.

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.

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.

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.

Checks críticos devem ser reproduzíveis fora da máquina do autor.

Idealmente:

local command
=
CI command

Diferença excessiva entre local e CI aumenta surpresa.

Nenhum check individual precisa provar tudo.

Confiança pode ser composta:

unit
+ type
+ contract
+ integration
+ security
+ revisão

O conjunto precisa cobrir o risco relevante.

Execute checks baratos primeiro.

Exemplo:

format
↓
lint
↓
type
↓
unit
↓
integration
↓
security
↓
E2E

Isso reduz custo desperdiçado.

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.

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.

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.

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.

Checks também envelhecem.

Podem deixar de refletir:

  • arquitetura;
  • risco;
  • dependências;
  • Spec;
  • threat model.

Gates precisam de manutenção.

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”.

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.

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.

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.

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.

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 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.


  1. Kent Beck, Test-Driven Development: By Example (2002), Preface / Red-Green-Refactor, pp. 1–3. Rastreabilidade interna: CLM-050. ↩

  2. Martin Fowler, Refactoring (1999), Chapter 5: Toward a Catalog of Refactorings, p. 85. Rastreabilidade interna: CLM-051. ↩ ↩2

  3. Kla Tantithamthavorn, Agentic Software Engineering (2026), Chapter 6: Verify, p. 102. Rastreabilidade interna: CLM-052. ↩

  4. Jeremy McEntire, Beyond Code (2026), Chapter 6: Mechanical Gates Over Advisory Review, p. 57. Rastreabilidade interna: CLM-008. ↩