Quelle est la meilleure façon de tester le code unitaire qui génère une sortie aléatoire?

Plus précisément, j'ai une méthode qui sélectionne n éléments d'une liste de telle sorte qu'a% d'entre eux répondent à un critère, et b % à une seconde, et ainsi de suite. Un exemple simplifié serait de sélectionner des 5 éléments, dont 50% ont une propriété avec la valeur "true", et 50% de "faux"; 50% du temps, la méthode retourne 2 vrai/3 fausses, et l'autre 50%, 3 true/2 faux.

Statistiquement parlant, cela signifie que plus de 100 courses, je devrais obtenir environ 250 true / 250 false, mais à cause du hasard, 240/260 est tout à fait possible.

Quelle est la meilleure façon de tester cela? Je suppose que même si techniquement 300/200 est possible, il devrait probablement échouer le test si cela se produit. Est-il généralement admis, la tolérance pour les cas comme cela, et si oui, comment déterminez-vous ce que c'est?

Edit: dans le code sur lequel je travaille, je n'ai pas le luxe d'utiliser un générateur de nombres pseudo-aléatoires, ou un mécanisme de le forcer à s'équilibrer au fil du temps, comme les listes qui sont sélectionnées out sont générés sur différentes machines. Je dois être en mesure de démontrer qu'au fil du temps, le nombre moyen d'éléments correspondant à chaque critère aura tendance au pourcentage requis.

26
demandé sur Flynn1179 2010-06-18 13:30:20

9 réponses

Le Hasard et les statistiques ne sont pas favorisés dans les tests unitaires. Les tests unitaires doivent toujours renvoyer le même résultat . Toujours. Pas la plupart du temps.

Ce que vous pourriez faire est d'essayer de supprimer le générateur aléatoire de la logique que vous testez. Ensuite, vous pouvez vous moquer du générateur aléatoire et renvoyer des valeurs prédéfinies.


Pensées supplémentaires:

Vous pouvez envisager de modifier l'implémentation pour la rendre plus testable. Essayez d'obtenir autant de valeurs aléatoires que possible. Vous pouvez par l'instance n'obtient qu'une valeur aléatoire pour déterminer l'écart par rapport à la distribution moyenne. Ce serait facile à tester. Si la valeur aléatoire est zéro, vous devriez obtenir la distribution exacte que vous attendez en moyenne. Si la valeur est par exemple 1.0, vous manquez la moyenne d'un facteur défini, par exemple de 10%. Vous pouvez également implémenter une distribution gaussienne, etc. Je sais que ce n'est pas le sujet ici, mais si vous êtes libre de l'implémenter comme vous le souhaitez, considérez la testabilité.

22
répondu Stefan Steinegger 2010-06-18 09:46:34

En fonction des informations statistiques dont vous disposez, déterminez une plage au lieu d'une valeur unique particulière.

4
répondu Chathuranga Chandrasekara 2010-06-18 09:31:47

De nombreux algorithmes probabilistes dans l'utilisation de l'informatique scientifique, par exemple pseudo - générateurs de nombres aléatoires , au lieu d'un générateur de nombres aléatoires true. Même s'ils ne sont pas vraiment aléatoires, un générateur de nombres aléatoires pseudo soigneusement choisi fera très bien le travail.

Un avantage de l' pseudo - -générateur de nombres aléatoires est que la séquence des nombres aléatoires qu'ils produisent est entièrement reproductibles. Puisque l'algorithme est déterministe, l' même semences serait génère toujours la même séquence. C'est souvent le facteur décisif pour lequel ils sont choisis en premier lieu, parce que les expériences doivent être reproductibles, les résultats reproductibles.

Ce concept est également applicable pour les tests. Les composants peuvent être conçus de telle sorte que vous pouvez brancher n'importe quelle source de nombres aléatoires. Pour les tests, vous pouvez ensuite utiliser des générateurs qui sont constamment ensemencés. Le résultat serait alors reproductible, ce qui est approprié pour les tests.

Notez que si, en fait, un true nombre aléatoire est nécessaire, vous pouvez encore test de cette façon, aussi longtemps que le composant dispose d'un enfichables source de nombres aléatoires. Vous pouvez re-brancher la même séquence (qui peut être vraiment aléatoire si nécessaire) au même composant pour le test.

4
répondu polygenelubricants 2010-06-18 09:47:12

Il me semble qu'il y a au moins trois choses distinctes que vous voulez tester ici:

  1. l'exactitude de la procédure qui génère une sortie en utilisant la source aléatoire
  2. que la distribution de la source aléatoire est ce que vous attendez
  3. que la distribution de la sortie est ce que vous attendez

1 devrait être déterministe et vous pouvez le tester par unité en fournissant un ensemble choisi de valeurs et d'entrées "aléatoires" connues et en vérifiant qu'il produit le correct connu sortie. Ce serait plus facile si vous structurez le code de sorte que la source aléatoire soit passée en argument plutôt que incorporée dans le code.

2 et 3 ne peuvent pas être testés absolument. Vous pouvez tester à un certain niveau de confiance choisi, mais vous devez être prêt pour que de tels tests échouent dans une fraction des cas. Probablement la chose que vous voulez vraiment surveiller est que le test 3 échoue beaucoup plus souvent que le test 2, car cela suggère que votre algorithme est faux.

Les tests à appliquer seront dépend de la distribution attendue. Pour 2, vous vous attendez probablement à ce que la source aléatoire soit uniformément distribuée. Il existe différents tests pour cela, en fonction de la façon dont vous voulez être impliqué, voir par exemple Tests pour les générateurs de nombres pseudo-aléatoires sur cette page.

La distribution attendue pour 3 dépendra beaucoup de ce que vous produisez exactement. Le cas simple 50-50 dans la question est exactement équivalent à tester une pièce juste, mais évidemment d'autres cas sera plus compliqué. Si vous pouvez déterminer ce que devrait être la distribution, un test chi-carré contre cela peut aider.

4
répondu walkytalky 2010-06-18 13:47:55

Cela dépend de l'utilisation que vous faites de votre suite de tests. Si vous l'exécutez toutes les quelques secondes parce que vous adoptez un développement piloté par les tests et un refactoring agressif,il est très important qu'il n'échoue pas de manière impitoyable, car cela provoque des perturbations majeures et réduit la productivité. Si vous exécutez vos tests une fois par nuit et avez un peu de temps pour enquêter sur les échecs vous pouvez être beaucoup strict.

En aucun cas vous ne devez déployer quelque chose qui conduira à des échecs fréquents Non étudiés - cela va à l'encontre de l'objectif d'avoir une suite de tests, et réduit considérablement sa valeur pour l'équipe.

3
répondu Kilian Foth 2010-06-18 09:35:34

, Vous devez tester la distribution des résultats dans un "simple" test unitaire, c'est à dire que le résultat est proche de la distribution désirée comme dans toute course. Pour votre exemple, 2 / faux 3 faux est OK, 4 true / 1 faux n'est pas OK en conséquence.

Vous pouvez également écrire des tests qui exécutent la méthode par exemple 100 fois et vérifie que la moyenne des distributions est "assez proche" du taux désiré. C'est un cas limite-l'exécution de plus gros lots peut prendre une importance significative vous pouvez donc exécuter ces tests séparément de vos tests unitaires "réguliers". En outre, comme le souligne Stefan Steinegger, un tel test va échouer de temps en temps si vous définissez "assez proche" plus strict, ou commencez à être dénué de sens si vous définissez le seuil trop vaguement. C'est donc un cas délicat...

2
répondu Péter Török 2010-06-18 09:39:11

Je pense que si j'avais le même problème, je construis probablement un intervalle de confiance pour détecter les anomalies si vous avez des statistiques sur la moyenne/stddev et autres. Donc, dans votre cas, si la valeur moyenne attendue est de 250, créez un intervalle de confiance de 95% autour de la moyenne en utilisant une distribution normale. Si les résultats sont en dehors de cet intervalle vous échouez le test.

Voir plus

1
répondu Anders 2010-06-18 10:21:34

Pourquoi ne pas re-factoriser le code de génération de nombres aléatoires et laisser le framework de test unitaire et le code source l'utiliser tous les deux? Vous essayez de tester votre algorithme et non la séquence aléatoire Non?

0
répondu Fanatic23 2010-06-18 10:54:43

Vous devez D'abord savoir quelle distribution devrait résulter de votre processus de génération de nombres aléatoires. Dans votre cas, vous générez un résultat qui est soit 0 ou 1 avec une probabilité de -0,5. Ceci décrit une distribution binomiale avec P = 0.5.

Étant donné la taille de l'échantillon de n, Vous pouvez construire (comme une affiche précédente l'a suggéré) un intervalle de confiance autour de la moyenne. Vous pouvez également faire de nombreuses déclarations sur la probabilité d'obtenir, par exemple, 240 ou moins de résultat lorsque N = 500.

Vous pouvez utiliser une hypothèse de distribution normale pour des valeurs de N supérieures à 20 tant que p n'est pas très grand ou très petit. Le poste Wikipedia a plus à ce sujet.

0
répondu Grembo 2010-06-18 19:15:24