170 votes

Données aléatoires dans les tests unitaires ?

J'ai un collègue qui écrit des tests unitaires pour des objets qui remplissent leurs champs avec des données aléatoires. Sa raison est que cela donne un plus large éventail de tests, puisqu'il testera un grand nombre de valeurs différentes, alors qu'un test normal n'utilise qu'une seule valeur statique.

Je lui ai donné un certain nombre de raisons différentes contre cela, les principales étant :

  • des valeurs aléatoires signifient que le test n'est pas vraiment répétable (ce qui signifie également que si le test peut échouer de manière aléatoire, il peut le faire sur le serveur de compilation et casser la compilation).
  • si c'est une valeur aléatoire et que le test échoue, nous devons a) corriger l'objet et b) nous forcer à tester cette valeur à chaque fois, afin de savoir que cela fonctionne, mais comme c'est aléatoire, nous ne savons pas quelle était la valeur.

Un autre collègue de travail a ajouté :

  • Si je teste une exception, des valeurs aléatoires ne garantiront pas que le test aboutisse à l'état attendu.
  • les données aléatoires sont utilisées pour le nettoyage d'un système et les tests de charge, mais pas pour les tests unitaires.

Quelqu'un peut-il ajouter des raisons supplémentaires que je peux lui donner pour qu'il arrête de faire ça ?

(Ou alternativement, est-ce une méthode acceptable d'écrire des tests unitaires, et moi et mon autre collègue avons tort) ?

39 votes

"les valeurs aléatoires signifient que le test n'est pas vraiment répétable" pas vrai, puisque les tets utiliseront des nombres pseudo-aléatoires. Fournissez la même graine initiale, obtenez la même séquence de tests "aléatoires".

19 votes

Anecdote : J'ai un jour écrit une classe d'exportation CSV, et des tests aléatoires ont révélé un bogue lorsque des caractères de contrôle étaient placés à la fin d'une cellule. Sans les tests aléatoires, je n'aurais jamais pensé à ajouter ce cas de test. A-t-il toujours échoué ? Non. Est-ce un test parfait ? Non. Est-ce qu'il m'a aidé à détecter et à corriger un bug ? Oui.

3 votes

Les tests peuvent aussi servir de documentation, pour expliquer ce que le code attend en entrée et ce qu'il attend en sortie. Avoir un test avec des données arbitraires claires peut être plus simple et plus explicatif qu'un code qui génère des données aléatoires.

83voto

Apocalisp Points 22526

Il y a un compromis. Votre collègue est en fait sur quelque chose, mais je pense qu'il s'y prend mal. Je ne suis pas sûr que des tests totalement aléatoires soient très utiles, mais ils ne sont certainement pas invalides.

Une spécification de programme (ou d'unité) est une hypothèse selon laquelle il existe un programme qui la satisfait. Le programme lui-même est alors une preuve de cette hypothèse. Ce que les tests unitaires devraient être, c'est une tentative de fournir des contre-preuves pour réfuter que le programme fonctionne selon la spécification.

Maintenant, vous pouvez écrire les tests unitaires à la main, mais c'est vraiment une tâche mécanique. Elle peut être automatisée. Tout ce que vous avez à faire est d'écrire la spécification, et une machine peut générer des tas et des tas de tests unitaires qui essaient de casser votre code.

Je ne sais pas quelle langue vous utilisez, mais voyez ici :

Java http://functionaljava.org/

Scala (ou Java) http://github.com/rickynils/scalacheck

Haskell http://www.cs.chalmers.se/~rjmh/QuickCheck/

.NET : http://blogs.msdn.com/dsyme/archive/2008/08/09/fscheck-0-2.aspx

Ces outils prennent votre spécification bien formée en entrée et génèrent automatiquement autant de tests unitaires que vous le souhaitez, avec des données générées automatiquement. Ils utilisent des stratégies de "réduction" (que vous pouvez modifier) pour trouver le scénario de test le plus simple possible pour casser votre code et pour s'assurer qu'il couvre bien les cas limites.

Bon test !

3 votes

+1 à ce sujet. ScalaCheck fait un travail phénoménal pour générer des données de test minimisées et aléatoires de manière répétable.

20 votes

Ce n'est pas aléatoire. C'est arbitraire. Grande différence :)

0 votes

Reductiotest.org ne semble plus exister, et Google ne m'a pas indiqué d'autre endroit. Une idée de l'endroit où il se trouve maintenant ?

48voto

Silver Dragon Points 2441

Ce type de test est appelé Test du singe . Lorsqu'il est bien fait, il peut faire sortir les insectes des coins les plus sombres.

Pour répondre à vos préoccupations en matière de reproductibilité, la bonne façon d'aborder cette question est d'enregistrer les entrées de test qui ont échoué, de générer un test unitaire qui recherche l'entrée de test. toute la famille du bogue spécifique ; et inclure dans le test unitaire l'entrée spécifique (à partir des données aléatoires) qui a causé l'échec initial.

29voto

Will Dean Points 25866

Il existe ici une solution à mi-chemin qui a une certaine utilité, qui consiste à ensemencer votre PRNG avec une constante. Cela vous permet de générer des données "aléatoires" qui peuvent être répétées.

Personnellement, je pense qu'il y a des endroits où les données aléatoires (constantes) sont utiles dans les tests - après avoir pensé que vous avez fait tous vos coins soigneusement réfléchis, l'utilisation de stimuli d'un PRNG peut parfois trouver d'autres choses.

4 votes

J'ai vu que cela fonctionnait bien sur un système qui avait beaucoup de verrouillages et de fils. La graine "aléatoire" était écrite dans un fichier à chaque exécution, puis, si une exécution échouait, nous pouvions déterminer le chemin emprunté par le code et écrire un test unitaire manuel pour le cas que nous avions manqué.

0 votes

Que signifie le sigle PRNG ?

0 votes

Générateur de nombres pseudo-aléatoires

19voto

Jimmy Bosse Points 412

Si vous faites du TDD, je dirais que les données aléatoires sont une excellente approche. Si votre test est écrit avec des constantes, alors vous ne pouvez garantir que votre code fonctionne pour la valeur spécifique. Si votre test échoue aléatoirement au serveur de construction, il y a probablement un problème dans la façon dont le test a été écrit.

Les données aléatoires permettront de s'assurer que toute refactorisation future ne repose pas sur une constante magique. Après tout, si vos tests sont votre documentation, la présence de constantes n'implique-t-elle pas qu'elle ne doit fonctionner que pour ces constantes ?

J'exagère mais je préfère injecter des données aléatoires dans mon test comme un signe que "la valeur de cette variable ne devrait pas affecter le résultat de ce test".

Je dirai cependant que si vous utilisez une variable aléatoire et que vous bifurquez votre test en fonction de cette variable, alors c'est une odeur.

18voto

mreggen Points 2940

Dans le livre Beau Code Il y a un chapitre intitulé "Beautiful Tests", dans lequel il présente une stratégie de test pour le système de gestion de l'information. Recherche binaire algorithme. Un paragraphe s'intitule "Random Acts of Testing", dans lequel il crée des tableaux aléatoires pour tester l'algorithme de manière approfondie. Vous pouvez lire une partie de ce texte en ligne sur Google Books, page 95 mais c'est un grand livre qui vaut la peine d'être lu.

En fait, cela montre simplement que la génération de données aléatoires pour les tests est une option viable.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X