O Que É um Teste Não Determinístico? Explicação
Um teste não determinístico pode retornar resultados diferentes com entradas idênticas porque depende de algo não controlado, como tempo, aleatoriedade, ordenação ou estado externo.
Determinismo é a propriedade de que as mesmas entradas sempre produzem a mesma saída. Um teste que não a tem é não confiável por construção: mesmo quando o código está correto, o resultado do teste pode variar. O não determinismo é o mecanismo subjacente por trás da maioria dos testes flaky.
Determinismo, definido
Um teste determinístico, dado o mesmo código e as mesmas entradas, sempre produz o mesmo resultado. Um teste não determinístico não produz, porque seu desfecho é influenciado por um fator que ele não controla. Essa dependência oculta é a raiz da flakiness.
Origens do não determinismo
- Tempo real de relógio, fusos horários ou datas que mudam entre execuções.
- Aleatoriedade sem seed ou ordenação de hash que varia por execução.
- Concorrência e ordenação de testes que se intercalam de forma diferente a cada vez.
- Rede, sistema de arquivos ou serviços de terceiros reais que retornam dados variáveis.
Por que é pior que um bug comum
Um bug determinístico falha de forma consistente e é simples de reproduzir e corrigir. Um teste não determinístico falha apenas às vezes, então é difícil de reproduzir, fácil de descartar como "só flaky" e corrói a confiança em toda a suíte. A intermitência é o problema.
Tornando testes determinísticos
Injete e congele o tempo. Faça seed da aleatoriedade explicitamente. Faça stub de serviços externos. Isole o estado e evite globais compartilhados. Espere por condições reais em vez de sleeps fixos. Cada mudança remove uma entrada não controlada até que o teste produza o mesmo resultado toda vez.
A perspectiva da Latchkey
O não determinismo no seu teste é um problema do lado do código que retries não conseguem realmente corrigir. Os managed runners com autocorreção da Latchkey, em vez disso, removem o não determinismo ambiental ao redor dos seus testes fazendo retry de falhas transitórias e mecânicas, de modo que uma instabilidade isolada não faça seu build falhar e a variação restante aponte claramente para o teste.
Principais conclusões
- Um teste não determinístico dá resultados diferentes com entradas idênticas.
- Tempo, aleatoriedade, ordenação e estado externo são os culpados usuais.
- Sua intermitência o torna mais difícil de corrigir do que um bug consistente.
- Controle cada entrada não controlada para restaurar o determinismo.