Ambos.
Testes determinísticos e não determinísticos têm diferentes casos de uso e valores diferentes para o seu conjunto. Geralmente não determinístico não pode fornecer a mesma precisão que o teste determinístico, que lentamente se transformou em "teste não determinístico não fornece valor". Isto é falso. Eles podem ser menos precisos, mas também podem ser muito mais amplos, o que tem seus próprios benefícios.
Vamos dar um exemplo: você escreve uma função que classifica uma lista de números inteiros. Quais seriam alguns dos testes unitários determinísticos que você consideraria úteis?
- Uma lista vazia
- Uma lista com apenas um elemento
- Uma lista com o mesmo elemento
- Uma lista com vários elementos exclusivos
- Uma lista com vários elementos, alguns dos quais são duplicados
- Uma lista com
NaN
, INT_MIN
eINT_MAX
- Uma lista que já está parcialmente classificada
- Uma lista com 10.000.000 de elementos
E isso é apenas uma função de classificação! Claro, você poderia argumentar que alguns deles são desnecessários ou que alguns deles podem ser descartados com raciocínio informal. Mas somos engenheiros e vimos o raciocínio informal explodir em nossa cara. Sabemos que não somos inteligentes o suficiente para entender completamente os sistemas que construímos ou manter totalmente a complexidade em nossas cabeças. É por isso que escrevemos testes em primeiro lugar. A adição de testes não determinísticos apenas diz que podemos não ser necessariamente inteligentes o suficiente para conhecer todos os bons testes a priori. Ao lançar dados semi-aleatórios em sua função, é muito mais provável que você encontre um caso extraviado que perdeu.
Obviamente, isso também não exclui os testes determinísticos. Testes não determinísticos ajudam a encontrar bugs em grandes áreas do programa. Depois de encontrar os bugs, no entanto, você precisa de uma maneira reproduzível para mostrar que foi corrigido. Então:
- Use testes não determinísticos para encontrar erros no seu código.
- Use testes determinísticos para verificar as correções no seu código.
Observe que isso significa que muitos conselhos sólidos sobre testes de unidade não se aplicam necessariamente a testes não determinísticos. Por exemplo, eles devem ser rápidos. Os testes de propriedades de baixo nível devem ser rápidos, mas um teste não determinístico como "simular um usuário clicando aleatoriamente nos botões do seu site e garantir que você nunca receba um erro de 500" deve favorecer a compreensão sobre a velocidade. Basta fazer um teste como esse, independentemente do seu processo de compilação, para não atrapalhar o desenvolvimento. Por exemplo, execute-o em sua própria caixa de teste particular.