Question

J'ai un collègue qui écrit des tests unitaires pour les objets qui remplissent leurs champs avec des données aléatoires.Sa raison est qu'il donne une plus grande gamme de tests, car elle permettra de tester un grand nombre de valeurs différentes, alors que le test n'utilise qu'une seule valeur statique.

Je lui avez donné un certain nombre de raisons différentes à l'encontre de cela, les principaux étant:

  • valeurs aléatoires signifie que le test n'est pas vraiment reproductible (ce qui signifie également que si le test peut ne pas aléatoire, il peut le faire sur le serveur de build et de briser la construction)
  • si c'est une valeur aléatoire et le test échoue, nous devons a) fixer l'objet et b) de la force de nous-mêmes pour tester cette valeur à chaque fois, donc nous savons qu'il fonctionne, mais comme c'est aléatoire, nous ne savons pas quelle était la valeur

Un autre collègue a ajouté:

  • Si je suis en train de tester une exception, les valeurs aléatoires de ne pas s'assurer que le test se termine dans l'état attendu
  • données aléatoires est utilisé pour le rinçage d'un système et de test de charge, pas pour les tests unitaires

Une autre personne peut en ajouter d'autres raisons que je peux donner sur lui pour l'amener à cesser de faire cela?

(Ou sinon, est-ce une méthode acceptable d'écrire des tests unitaires, et moi et mon autre collègue de travail sont mauvaises?)

Était-ce utile?

La solution

Il y a un compromis.Votre collègue est en fait sur quelque chose, mais je pense qu'il fait ce mal.Je ne suis pas sûr que c'est totalement aléatoire, le test est très utile, mais c'est certainement pas invalide.

Un programme (ou unité) de la spécification est une hypothèse qu'il existe un programme qui répond à elle.Le programme lui-même est alors la preuve de cette hypothèse.Ce que les tests unitaires doivent être est une tentative de fournir des contre-preuves pour réfuter que le programme fonctionne selon les spécifications.

Maintenant, vous pouvez écrire les tests unitaires à la main, mais c'est vraiment une tâche mécanique.Il 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 est la langue que vous utilisez, mais le voir 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 permettront de prendre votre bien-formé spécifications d'entrée et de générer automatiquement comme unité de nombreux essais que vous le souhaitez, avec des données générées automatiquement.Ils utilisent un "rétrécissement" des stratégies (que vous pouvez modifier) pour trouver le plus simplement possible des cas de test à casser votre code et assurez-vous qu'elle couvre les cas de bord bien.

Heureux d'essais!

Autres conseils

Ce type de test est appelé un Monkey test.Lorsque bien fait, il peut traquer les bugs de la vraiment des coins sombres.

Pour répondre à vos préoccupations au sujet de reproductibilité:la bonne façon d'aborder cette, faire le bilan de l'échec du test des entrées, générer un test unitaire, qui sondes pour l' toute la famille de la bogue spécifique;et d'inclure dans l'unité de test une entrée spécifique (à partir des données aléatoires), qui a causé l'échec initial.

Il est à mi-chemin de la maison, là, qui a une certaine utilisation, ce qui est de la graine de votre GÉNÉRATEUR avec une constante.Qui permet de générer des "aléatoire" de données qui est répétable.

Personnellement, je pense qu'il y a des endroits où (constant) données aléatoires est utile pour les tests - après vous pensez que vous avez fait tous vos soigneusement pensé coins, à l'aide de stimuli à partir d'un GÉNÉRATEUR peut parfois trouver d'autres choses.

Dans le livre Beau Code, il y a un chapitre intitulé "la Belle de Tests", où il passe par une stratégie de test pour la Recherche Binaire l'algorithme.Un paragraphe est appelé "Random Acts of Testing", dans lequel il crée aléatoire des tableaux de tester l'algorithme.Vous pouvez lire certains de ces en ligne sur Google Livres, page 95, mais c'est un grand livre a de la valeur.

Donc, fondamentalement, cela montre juste que la génération de données aléatoires pour les tests est une option viable.

Un avantage pour quelqu'un qui cherche à les tests, c'est que l'arbitraire des données est clairement pas important.J'ai trop vu des tests qui ont impliqué des dizaines de morceaux de données et il peut être difficile de dire ce qui doit être et ce qui arrive juste à être de cette façon.E. g.Si une adresse de validation de la méthode est testée avec un zip code et toutes les autres données sont aléatoires, alors vous pouvez être sûr que le code postal est le seul élément important.

Si vous faites TDD alors je dirais que des données aléatoires est 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 est au hasard ou à défaut, le serveur de build il y a probablement un problème avec la façon dont le test a été écrit.

Données aléatoires aidera à s'assurer que toutes les refactoring ne sera pas compter sur la magie de la constante.Après tout, si vos tests sont à votre documentation, puis n'est-ce pas la présence de constantes impliquent, on a besoin de travailler 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 puis fourche votre test en fonction de cette variable, alors que c'est l'odeur.

  • si c'est une valeur aléatoire et le test échoue, nous devons a) fixer l'objet et b) de la force de nous-mêmes pour tester cette valeur à chaque fois, donc nous savons qu'il fonctionne, mais comme c'est aléatoire, nous ne savons pas quelle était la valeur

Si votre cas de test n'est pas avec exactitude ce qu'il en est des tests, peut-être vous avez besoin de ré-encoder les cas de test.J'ai toujours envie d'avoir les journaux que je peux renvoyer à pour des cas de test pour que je sache exactement ce qui a causé l'échec si l'utilisation statique ou des données aléatoires.

Votre co-travailleur est en train de faire test aléatoire, bien qu'il ne sait pas à ce sujet.Ils sont particulièrement utiles dans les systèmes de serveurs.

Je suis en faveur d'essais au hasard, et je les écris.Toutefois, si elles sont appropriées dans un environnement de compilation et de test des suites qu'ils devraient être inclus dans une approche plus nuancée de la question.

Exécuter localement (par exemple, pour la nuit sur votre boîte de dev) randomisés essais ont constaté des bugs à la fois évidente et obscur.L'obscur sont des arcanes suffit que je pense que le test de dépistage aléatoire était vraiment la seule réaliste à rincer à sortir.Comme un test, j'ai pris un dur-à-trouver un bug découvert par test aléatoire et avait une demi-douzaine de fissure développeurs d'examen de la fonction (une dizaine de lignes de code) où il est survenu.Aucun n'a été en mesure de le détecter.

Beaucoup de vos arguments contre randomisés de données sont des saveurs de "le test n'est pas reproductible".Cependant, bien écrit randomisés test de capture de la semence utilisée pour démarrer l'étude randomisée de semences et de sortie en cas d'échec.En plus de vous permettre de répéter le test à la main, cela vous permet de carrément créer un nouveau test qui test le problème spécifique à coder en dur les graines de ce test.Bien sûr, il est probablement plus agréable à la main le code explicite de test couvrant ce cas, mais la paresse a ses vertus, et cela vous permet même de essentiellement auto-générer de nouveaux cas de test à partir de l'échec de la graine.

Le seul point que vous faites que je ne peux pas le débat, cependant, est qu'il se casse les systèmes de construction.La plupart de construire et d'intégration continue, les tests d'attendre les tests pour faire la même chose, à chaque fois.Donc un test qui échoue au hasard va créer le chaos, au hasard d'échouer et de pointer du doigts les changements qui ont été inoffensifs.

Une solution est donc de continuer à exécuter votre randomisés essais dans le cadre de la construction et de l'IC de tests, mais le faire fonctionner avec un fixe de semences, pour un nombre fixe d'itérations.D'où le test fait toujours la même chose, mais encore explore un tas de l'espace d'entrée (si vous l'exécutez pour de multiples itérations).

Localement, par exemple, lors de la modification de la classe concernée, vous êtes libres de les utiliser pour plus d'itérations ou avec d'autres graines.Si le test aléatoire devient de plus en plus populaire, on pourrait même imaginer une suite de tests qui sont connus pour être le hasard, ce qui pourrait être exécuté avec différentes graines (donc avec l'augmentation de la couverture au fil du temps), et où les pannes ne signifie pas la même chose que déterministe systèmes CI (c'est à dire, pistes ne sont pas associés 1:1 avec les modifications de code et afin de ne pas pointer du doigt un changement particulier, lorsque les choses ne).

Il y a beaucoup à dire pour des essais randomisés, particulièrement bien écrit, donc ne soyez pas trop prompts à rejeter!

Pouvez-vous générer des données aléatoires une fois (je veux dire exactement une fois, pas une fois par test), puis l'utiliser dans tous les tests par la suite?

Je peux certainement voir la valeur dans la création aléatoire de données de test dans les cas que vous n'avez pas pensé, mais tu as raison, d'avoir des tests unitaires qui peuvent au hasard de réussite ou d'échec est une mauvaise chose.

Vous devez vous demander quel est le but de votre test.
Les tests unitaires sont sur la vérification de la logique, du code des flux et des interactions entre les objets.À l'aide de valeurs aléatoires essaie de réaliser un objectif différent, ce qui réduit les tester et de simplicité.Il est acceptable pour des raisons de lisibilité (génération d'UUID, ids, clés,etc.).
Spécifiquement pour les tests unitaires, je ne me souviens même d'une fois cette méthode a réussi à trouver des problèmes.Mais j'ai vu beaucoup de déterminisme problèmes (dans les tests) en essayant de faire le malin avec des valeurs aléatoires et principalement au hasard des dates.
Les tests aléatoires est une approche valable pour les tests d'intégration et de bout en bout tests.

Si vous utilisez des entrées aléatoires pour vos tests, vous devez vous connecter les entrées de sorte que vous pouvez voir ce que les valeurs sont.De cette façon, si il y a certains cas limites que vous rencontrez, vous peut écrire le test de la reproduire.J'ai entendu les mêmes raisons de personnes pour ne pas utiliser aléatoire d'entrée, mais une fois que vous avez aperçu les valeurs réelles utilisées pour un test particulier alors il n'est pas un problème.

La notion de "arbitraire" de données est très utile aussi comme une manière de signifier quelque chose qui est pas important.Nous avons quelques tests d'acceptation qui viennent à l'esprit là où il y a beaucoup de données sur le bruit, qui est sans importance pour le test à la main.

En fonction de votre objet/app, des données aléatoires aurait une place dans les tests de charge.Je pense que le plus important serait d'utiliser des données explicitement tests les conditions aux limites des données.

Nous viens de tomber sur ce sujet aujourd'hui.Je voulais pseudo-aléatoire (donc, il devrait ressembler à des données audio compressées en termes de taille).Je TODO avais que je voulais aussi déterministe.rand() était différente sur OSX que sur Linux.Et si je re-semé, il peut modifier à tout moment.Nous avons donc changé pour être déterministe, mais encore pseudo-aléatoire:le test est répétable, autant que l'utilisation en conserve les données (mais plus facilement à l'écrit).

C'était PAS les tests par hasard la force brute à travers les chemins de code.C'est toute la différence:encore déterministe, toujours reproductibles, toujours à l'aide de données qui ressemble à véritable entrée pour exécuter un ensemble d'intéressant vérifie sur le bord des cas, dans une logique complexe.Encore des tests unitaires.

Le fait d'être toujours admissible est aléatoire?Parlons-en plus de la bière.:-)

Je peux envisager trois solutions pour le test de problème de données:

  • Test avec des données fixes
  • Test avec des données aléatoires
  • Générer des données aléatoires une fois, puis l'utiliser comme vos données fixes

Je recommanderais de faire tous les ci-dessus.C'est, écrire reproductible tests unitaires avec les deux certains cas bord travaillé à l'aide de votre cerveau, et certains randomisés données qui vous générer qu'une seule fois.Ensuite, écrire une série de randomisée tests que vous exécutez ainsi.

Les essais randomisés ne doit jamais s'attendre à attraper quelque chose de votre reproductible tests miss.Vous devriez viser à couvrir le tout avec de tests reproductibles, et d'envisager l'étude randomisée de tests un bonus.Si ils trouvent quelque chose, il devrait être quelque chose que vous ne pouvait pas raisonnablement prévisibles;un véritable excentrique.

Comment pouvez-vous les gars exécuter le test à nouveau quand il a échoué pour voir si il a fixé?I. e.il perd la répétabilité des essais.

Alors que je pense qu'il ya probablement une certaine valeur en jetant un chargement de données aléatoires à des tests, comme mentionné dans d'autres réponses, on tombe plus sous la rubrique de test de charge qu'autre chose.C'est un peu un "test-par-l'espoir" de la pratique.Je pense que, dans la réalité, votre gars est tout simplement pas thinkng à propos de ce qu'il est en train de tester, et pour qui l'absence de pensée en espérant aléatoire finira par piège de mystérieux erreur.

Donc l'argument que je voudrais utiliser avec lui c'est qu'il est paresseux.Ou, pour le dire d'une autre manière, s'il ne prend pas le temps de comprendre ce qu'il est en train de tester, c'est probablement montre qu'il n'a pas vraiment à comprendre le code qu'il écrit.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top