É melhor ter um
- Conjunto de testes determinísticos, que resulta nos mesmos testes
- Conjunto de testes não determinísticos, que possivelmente cobre mais casos
?
Exemplo: você escreve um conjunto de testes para testar a funcionalidade do controlador em um aplicativo MVC. O controlador requer dados do aplicativo de um banco de dados como entrada durante o teste. Existem duas opções para fazer isso:
- Você codifica quais linhas do banco de dados de teste são selecionadas como entrada (por exemplo, as linhas 10 e 412)
- Você usa um gerador de números aleatórios para escolher aleatoriamente os dados do banco de dados (duas linhas selecionadas por um gerador de números aleatórios)
A primeira é determinística: toda execução do teste para a mesma revisão de código deve produzir o mesmo resultado. A segunda é não determinística: toda execução do conjunto de testes tem a possibilidade de gerar um resultado diferente. Os dados escolhidos aleatoriamente podem, no entanto, ser uma melhor representação dos casos extremos de dados. Pode simular um usuário alimentando nossos controladores com dados imprevisíveis melhor?
Quais são os motivos para escolher um sobre o outro?
Respostas:
Quando todas as execuções do conjunto de testes oferecem a possibilidade de produzir um resultado diferente, o teste é quase completamente inútil - quando o conjunto mostra um erro, você tem uma grande chance de não conseguir reproduzi-lo e quando tenta corrigir o erro. bug, você não pode verificar se sua correção funciona.
Portanto, quando achar que precisa usar algum tipo de gerador de números aleatórios para gerar seus dados de teste, sempre inicialize o gerador com a mesma semente ou persista seus dados de teste aleatórios em um arquivo antes de alimentá-lo em seu teste, para que você possa executar novamente o teste novamente com exatamente os mesmos dados da execução anterior. Dessa forma, você pode transformar qualquer teste não determinístico em um determinístico.
EDIT: Usar um gerador de números aleatórios para escolher alguns dados de teste é IMHO, às vezes, um sinal de preguiça de escolher boas dados de teste. Em vez de lançar 100.000 valores de teste escolhidos aleatoriamente e esperar que isso seja suficiente para descobrir todos os erros sérios por acaso, use melhor seu cérebro, escolha 10 a 20 casos "interessantes" e use-os para o conjunto de testes. Isso resultará não apenas em uma melhor qualidade de seus testes, mas também em um desempenho muito maior do conjunto.
fonte
Tanto determinístico quanto não determinístico têm um lugar
Eu os dividiria da seguinte maneira:
Testes unitários.
Eles devem ter testes determinísticos e repetíveis com os mesmos dados exatos todas as vezes. Os testes de unidade acompanham seções de código específicas e isoladas e devem testá-las de maneira determinística.
Testes de estresse funcionais e de entrada.
Eles podem usar a abordagem não determinística com as seguintes advertências:
fonte
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?
NaN
,INT_MIN
eINT_MAX
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:
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.
fonte
Você realmente não quer determinístico versus não determinístico.
O que você pode querer é "sempre o mesmo" vs. "nem sempre o mesmo".
Por exemplo, você pode ter um número de compilação que aumenta a cada compilação e quando deseja alguns números aleatórios, inicializa um gerador de números aleatórios com o número de compilação como semente. Portanto, a cada compilação, você faz seus testes com valores diferentes, oferecendo mais chances de encontrar bugs.
Mas quando um bug é encontrado, tudo o que você precisa fazer é executar o teste com o mesmo número de compilação e é reproduzível.
fonte