Fazendo trabalho de pesquisa e desenvolvimento, muitas vezes me pego escrevendo programas que têm um grande grau de aleatoriedade em seu comportamento. Por exemplo, quando trabalho em Programação Genética, geralmente escrevo programas que geram e executam código fonte aleatório arbitrário.
Um problema ao testar esse código é que os bugs geralmente são intermitentes e podem ser muito difíceis de reproduzir. Isso vai além de apenas definir uma semente aleatória com o mesmo valor e iniciar a execução novamente.
Por exemplo, o código pode ler uma mensagem do buffer de anel kernal e, em seguida, fazer saltos condicionais no conteúdo da mensagem. Naturalmente, o estado do buffer do anel será alterado quando mais tarde tentar reproduzir o problema.
Embora esse comportamento seja um recurso, ele pode disparar outro código de maneiras inesperadas e, portanto, frequentemente revela bugs que os testes de unidade (ou testadores humanos) não encontram.
Existem práticas recomendadas estabelecidas para testar sistemas desse tipo? Nesse caso, algumas referências seriam muito úteis. Caso contrário, outras sugestões são bem-vindas!
fonte
Respostas:
É útil adicionar ganchos, como sugerido, para recriar estados exatos. Também instrumentar o sistema para que ele possa despejar suas "sementes" (no seu caso, incluindo a semente PRNG, bem como o buffer de anel do kernel e quaisquer outras fontes de entrada não determinística).
Em seguida, execute seus testes com entrada aleatória verdadeira e estilo de regressão com todos os casos interessantes descobertos anteriormente.
No caso particular de seu acesso ao kernel, eu recomendaria fazer uma zombaria em qualquer caso. Use o mock para forçar classes de equivalência com menor probabilidade de aparecer na prática, no espírito de "vazio" e "cheio" para contêineres, ou "0, 1, 2 ^ n, 2 ^ n + 1, muitos" para coisas contáveis. Em seguida, você pode testar com o mock e com o real, sabendo que você lidou e testou os casos em que você pensou até agora.
Basicamente, o que estou sugerindo equivale a uma mistura de entradas determinísticas e não determinísticas, com as determinísticas sendo uma mistura daquelas em que você pode pensar e das que foram surpreendidas.
fonte
Uma coisa razoável a se fazer é propagar o gerador de números aleatórios com um valor constante para os testes, para que você obtenha um comportamento determinístico.
fonte
Eu acho que o teste estatístico é o único caminho. Assim como os números aleatórios são "testados" quanto à aleatoriedade por testes estatísticos, também precisam ser algoritmos que usam comportamento aleatório.
Simplesmente execute o algoritmo várias vezes com entrada igual ou diferente e compare-o. O problema com essa abordagem é um aumento maciço no tempo computacional necessário para concluir o teste.
fonte
Não sou especialista neste domínio, mas há uma literatura científica relativa ao teste estocástico do programa.
Se você não pode criar facilmente classes de teste, um teste estatístico pode ser usado, como #Euphoric disse. Borning et al. compare uma abordagem tradicional e uma estatística. Uma generalização dos testes estatísticos sugeridos pelo @Euphoric pode ser o discutido por Whittaker. Ele sugeriu criar um modelo estocástico do comportamento desejado (estocástico, no seu caso) e, em seguida, gerar casos de teste específicos a partir desse modelo (consulte seu artigo dedicado ).
fonte