Testes instáveis
O teste que passa e falha sem mudar nada — as cinco causas, e por que repetir não é a correção.
Um teste instável é pior que nenhum: ele ensina o time a rodar o CI de novo em vez de ler a falha. E no dia em que a falha é real, ela é tratada como ruído. Toda instabilidade tem uma causa, e a causa quase sempre é uma destas cinco.
| Causa | Sintoma | Correção |
|---|---|---|
| tempo | falha perto da meia-noite, ou numa máquina lenta | relógio falso: Crucible.com_relogio / freeze_time |
| ordem | passa sozinho, falha na suíte | estado compartilhado — um banco novo por teste |
| aleatoriedade | falha uma vez em vinte | semente fixa, ou teste por propriedade com a semente no relatório |
| concorrência | falha só no CI, que tem outro número de núcleos | sincronizar de verdade; medir com Crucible.corrida |
| medida absoluta | “devia levar menos de 50 ms” | comparar uma razão contra a mesma máquina |
Tempo: o relógio que você controla#
dataforge
adopt Arcane.Crucible
action vencido(prazo, agora):
yield agora bigger prazo
crucible "prazo":
trial "vence depois do prazo, e nao antes":
expect vencido(1000, 999) is no
expect vencido(1000, 1000) is no
expect vencido(1000, 1001) is yes
r := Crucible.run()
assert r["falhou"] is 0
// A regra recebe 'agora' como argumento. Uma acao que chama time()
// por dentro so e testavel na hora certa do dia.Repetir não é corrigir#
Crucible.flaky(acao, tentativas) existe, e devolve quantas tentativas foram precisas — um teste que precisa de três toda vez não é instável, está quebrado. Use-o como diagnóstico, nunca como correção permanente.
Continue em Cenários de concorrência e relógio.