Verificação e Evals|INEMA.CLUB-PRO

Aula 3 · 20 min

Testes congelados e guarda de diff nos testes

Se o agente pode mexer no juiz, o juiz não vale. Congelar os testes é escrevê-los antes, guardar um retrato deles fora do alcance do agente e reprovar qualquer mudança. Nesta aula você vê que proteger só a pasta tests/ não basta: um conftest.py na raiz pula tudo e o pytest sai com 0.

Começar a aula
Placas de referência lacradas em sacos antiestáticos e caixas de acrílico numa prateleira de aço.

Nesta aula você vai

  1. 1O que é "o juiz": testes, conftest.py em qualquer nível e a config do pytest
  2. 2Manifesto com hash e mínimo de testes, gravado fora do repo
  3. 3As cinco reprovações: apagado, mexido, novo, poucos, pulado
  4. 4O furo do conftest no loop headless e a correção

Objetivo: congelar o juiz (testes, conftest, config) com hash e mínimo de testes fora do repo e reprovar apagar, pular ou mexer.

01Congelar antes, conferir depois

Clique em cada etapa.

Clique em cada bloco do diagrama para ver o que ele faz.

Código 0 do pytest não é prova: com todos os testes pulados ele também sai 0.

02Ensaio: três agentes contra a guarda

Congela antes de cada agente e confere depois. GUARDA_DIR fica fora do projeto.

Terminal · apaga, conftest e bom
K=~/projetos/loop-r-eng-verificacao-v72/kit
export GUARDA_DIR=/tmp/ensaio-verif/guarda       # fora do repo
for modo in apaga conftest bom; do
  bash $K/ensaio.sh > /dev/null && cd /tmp/ensaio-verif/proj
  python3 $K/guarda-testes.py congelar .          # ANTES do agente
  $K/agente-falso.sh $modo < /dev/null > /dev/null
  echo "## $modo"; python3 $K/guarda-testes.py conferir .; echo "saída: $?"
done
Exemplo do repositório
congelado: 2 arquivos protegidos, mínimo de 3 testes → /tmp/ensaio-verif/guarda/guarda.json
## apaga
testes: no tests ran in 0.00s (código 5, mínimo 3 passed)
APAGADO  tests/test_slug.py
POUCOS   0 passed, mínimo 3
GUARDA: REPROVADO
saída: 1
congelado: 2 arquivos protegidos, mínimo de 3 testes → /tmp/ensaio-verif/guarda/guarda.json
## conftest
testes: 3 skipped in 0.00s (código 0, mínimo 3 passed)
NOVO     conftest.py
POUCOS   0 passed, mínimo 3
PULADO   3 skipped
GUARDA: REPROVADO
saída: 1
congelado: 2 arquivos protegidos, mínimo de 3 testes → /tmp/ensaio-verif/guarda/guarda.json
## bom
testes: 3 passed in 0.00s (código 0, mínimo 3 passed)
GUARDA: OK
saída: 0

Os 2 arquivos protegidos são tests/test_slug.py e pytest.ini. No modo conftest, repare em "código 0": o pytest achou que estava tudo bem.

03O furo do conftest no loop headless

O loop-longrun.sh do curso 2 reverte o que o agente mexe em PROTEGIDOS. Com o PROTEGIDOS de exemplo ("tests/ pytest.ini"), um conftest.py na raiz passa e o teste final "passa" sem nenhum teste rodar. Ensaio com agente falso, sem custo.

Terminal · o furo (PROTEGIDOS de exemplo)
K=~/projetos/loop-r-eng-verificacao-v72/kit; L=~/projetos/execucao-longa/tools
bash $K/ensaio.sh > /dev/null && cd /tmp/ensaio-verif/proj
printf '#!/usr/bin/env bash\nexec %s/agente-falso.sh conftest\n' $K > /tmp/agente-conftest.sh
chmod +x /tmp/agente-conftest.sh
$L/novo-longrun.sh $PWD slug > /dev/null && D=$(ls -d $PWD/longrun/*)
echo "Implemente slug() em slug.py. Não mexa em tests/." > $D/prompt.md
cat > $D/loop.env <<'ENV'
TESTE_RAPIDO="python3 -m pytest -q"
TESTE_FINAL="python3 -m pytest -q"
PROTEGIDOS="tests/ pytest.ini"
PERMITIDOS="slug.py"
MAX_CICLOS=3
MIN_CICLO=2
MEM=1G
ESTAGNACAO=3
ENV
git add -A && git commit -qm "longrun: pasta"
CODEX_BIN=/tmp/agente-conftest.sh $L/loop-longrun.sh $D; echo "saída: $?"
Terminal · a correção (conftest protegido + guarda como teste final)
bash $K/ensaio.sh > /dev/null && cd /tmp/ensaio-verif/proj        # recomeça do zero
export GUARDA_DIR=/tmp/ensaio-verif/guarda
python3 $K/guarda-testes.py congelar . > /dev/null
$L/novo-longrun.sh $PWD slug > /dev/null && D=$(ls -d $PWD/longrun/*)
echo "Implemente slug() em slug.py. Não mexa em tests/." > $D/prompt.md
cat > $D/loop.env <<ENV
TESTE_RAPIDO="python3 -m pytest -q"
TESTE_FINAL="GUARDA_DIR=$GUARDA_DIR python3 $K/guarda-testes.py conferir ."
PROTEGIDOS="tests/ pytest.ini *conftest.py"
PERMITIDOS="slug.py"
MAX_CICLOS=3
MIN_CICLO=2
MEM=1G
ESTAGNACAO=3
ENV
git add -A && git commit -qm "longrun: pasta"
CODEX_BIN=/tmp/agente-conftest.sh $L/loop-longrun.sh $D; echo "saída: $?"
ls conftest.py; grep -c "revertido pelo loop" $D/failures.md
Exemplo do repositório
## o furo
2026-10-19 04:38:48 início: rápido=0 passed · agente=codex · teto 3x2min · mem 1G
2026-10-19 04:38:48 ciclo 1: começa
2026-10-19 04:38:48 ciclo 1: agente saiu rc=0 em 0s
2026-10-19 04:38:48 ciclo 1: rápido=0 passed (melhor antes: 0)
2026-10-19 04:38:48 ciclo 1: checkpoint commitado
2026-10-19 04:38:49 CONCLUÍDO no ciclo 1: teste final passou ()
saída: 0

## a correção
2026-10-19 04:38:49 início: rápido=0 passed · agente=codex · teto 3x2min · mem 1G
2026-10-19 04:38:49 ciclo 1: começa
2026-10-19 04:38:49 ciclo 1: agente saiu rc=0 em 0s
2026-10-19 04:38:49 ciclo 1: agente mexeu em arquivo protegido → revertido, ciclo falho
error: pathspec 'conftest.py' did not match any file(s) known to git
2026-10-19 04:38:49 ciclo 1: checkpoint commitado
(… ciclos 2 e 3 iguais …)
2026-10-19 04:38:50 PARADO: 3 ciclos sem avanço mensurável — ver failures.md
saída: 2
ls: cannot access 'conftest.py': No such file or directory
3

"teste final passou ()": os parênteses vazios são a contagem de passed, que não existe. Na correção, a linha error: pathspec é inofensiva: o git checkout não conhece o arquivo novo e o git clean logo depois o remove.

04Prática

Ensaio da guarda, o furo do loop e a guarda no seu projeto.

E7 · Três agentes contra a guarda

10 min

Rode o laço apaga, conftest, bom.

Pronto quando: apaga e conftest terminam em GUARDA: REPROVADO com saída: 1 (conftest com a linha NOVO conftest.py); bom termina em GUARDA: OK com saída: 0.

E8 · Ver o furo e fechar

15 min

Rode os dois blocos do loop headless. Você precisa do kit execucao-longa em ~/projetos/execucao-longa (curso 2).

Pronto quando: o primeiro imprime CONCLUÍDO no ciclo 1: teste final passou () e saída: 0; o segundo PARADO: 3 ciclos sem avanço mensurável, saída: 2, e o último comando imprime 3.

E9 · Guarda no seu projeto

15 min

Num projeto seu com pytest, congele no commit de base e confira. Se o projeto usa outro arquivo de config do pytest, ponha em PROTEGIDOS.

Pronto quando: python3 $K/guarda-testes.py congelar . imprime congelado: N arquivos protegidos, mínimo de M testes com M igual ao total de testes, e python3 $K/guarda-testes.py conferir .; echo $? → GUARDA: OK e 0.

05Teste da aula

Pergunta 1 de 4

Por que o manifesto da guarda fica em GUARDA_DIR, fora do repo?competência

06Em três frases

O juiz é maior que tests/conftest.py em qualquer nível e a config do pytest também decidem o que roda.
Retrato fora do alcanceHash e mínimo de testes gravados antes do agente, num lugar onde ele não escreve.
Código 0 não bastaExija o mínimo de passed e nenhum pulado; é isso que fecha o furo do loop headless.

Para ir além

Aula anteriorPróxima aula