Junit4: Ordre de test vraiment aléatoire avec possibilité de semences données en externe

Créé le 26 août 2015  ·  9Commentaires  ·  Source: junit-team/junit4

Par défaut, junit exécute le test dans l'ordre par défaut basé sur le code de hachage du nom de la méthode. En Java, les hashcodes de la chaîne ne changent pas entre les exécutions, donc l'ordre est aléatoire, mais constant pour un ordinateur donné. Cela pourrait conduire à des erreurs imprévisibles.

Réf : https://github.com/junit-team/junit/blob/master/src/main/java/org/junit/internal/MethodSorter.java#L13

$ groovysh 
Groovy Shell (1.8.6, JVM: 1.7.0_79)
Type 'help' or '\h' for help.
---------------------------------------------------------------------------------------------------------------------------------------------------------
groovy:000> a = 'testSample'
===> testSample
groovy:000> a.hashCode()
===> 1710059740
groovy:000>
$ groovysh 
Groovy Shell (1.8.6, JVM: 1.7.0_79)
Type 'help' or '\h' for help.
---------------------------------------------------------------------------------------------------------------------------------------------------------
groovy:000> a = 'testSample'
===> testSample
groovy:000> a.hashCode()
===> 1710059740
groovy:000>

Pour corriger cet enchantement, il devrait y avoir une option d'ordre vraiment aléatoire à spécifier explicitement dans le cas de test en utilisant @FixMethodOrder .

Je propose de suivre l'implémentation --order option aléatoire Rspec --order rand:3455 . Il garantit que les tests seront exécutés dans le même ordre, il est donc possible de rechercher les bogues d'ordre d'exécution.

Citer:

Lorsque vous utilisez --order random, RSpec imprime le nombre aléatoire qu'il a utilisé pour amorcer le randomiseur. Lorsque vous pensez avoir trouvé un bogue de dépendance à l'ordre, vous pouvez transmettre la graine et l'ordre restera cohérent :

--commande rand:3455

Exemple d'exécution :

$ rspec test.rb --order rand

Randomized with seed 64539

testing
  should equal 5
  should contain 'test'

Finished in 0.02 seconds (files took 0.0092 seconds to load)
2 examples, 0 failures

Randomized with seed 64539

$ rspec test.rb --order rand

Randomized with seed 12834

testing
  should contain 'test'
  should equal 5

Finished in 0.02 seconds (files took 0.0088 seconds to load)
2 examples, 0 failures

Randomized with seed 12834

$ rspec test.rb --order rand:12834

Randomized with seed 12834

testing
  should contain 'test'
  should equal 5

Finished in 0.02 seconds (files took 0.0083 seconds to load)
2 examples, 0 failures

Randomized with seed 12834

Référence aléatoire Rspec : http://blog.davidchelimsky.net/blog/2012/01/04/rspec-28-is-released/

Commentaire le plus utile

Salut @Endron. Votre argument est bon, mais veuillez regarder de plus près dans l'implémentation --order random option Rspec --order rand:3455 . Il garantit que les tests seront exécutés dans le même ordre.

Citer:

Lorsque vous utilisez --order random , RSpec imprime le nombre aléatoire qu'il a utilisé pour amorcer le randomiseur. Lorsque vous pensez avoir trouvé un bogue de dépendance à l'ordre, vous pouvez transmettre la graine et l'ordre restera cohérent :

--order rand:3455

Ceci est un exemple d'exécution (vous pouvez voir que la graine est affichée en ligne de commande): https://travis-ci.org/coi-gov-pl/puppet-jboss/jobs/81936397#L556

Tous les 9 commentaires

Puis-je suggérer knuth shuffle pour déterminer l'ordre d'exécution ?
Info-
https://en.wikipedia.org/wiki/Fisher-Yates_shuffle

code source-
http://algs4.cs.princeton.edu/11model/Knuth.java.html

De l' ordre d'exécution du test

De par sa conception, JUnit ne spécifie pas l'ordre d'exécution des appels de méthode de test. Jusqu'à présent, les méthodes étaient simplement invoquées dans l'ordre renvoyé par l'API de réflexion. Cependant, l'utilisation de l'ordre JVM est imprudente car la plate-forme Java ne spécifie aucun ordre particulier, et en fait JDK 7 renvoie un ordre plus ou moins aléatoire. Bien sûr, un code de test bien écrit ne supposerait aucun ordre, mais certains le font, et un échec prévisible vaut mieux qu'un échec aléatoire sur certaines plates-formes.

A partir de la version 4.11, JUnit utilisera par défaut un ordre déterministe, mais non prévisible (MethodSorters.DEFAULT). Pour modifier l'ordre d'exécution du test, annotez simplement votre classe de test à l'aide de

@FixMethodOrder(MethodSorters.JVM) : laisse les méthodes de test dans l'ordre renvoyé par la JVM. Cet ordre peut varier d'une série à l'autre.

@FixMethodOrder(MethodSorters.NAME_ASCENDING) : trie les méthodes de test par nom de méthode, dans l'ordre lexicographique.

Le problème ici est qu'il y a en fait deux odeurs de test qui sont interconnectées :

  1. Tests en fonction de l'ordre d'exécution
  2. Tests non reproductibles

Mettre les tests dans un ordre vraiment aléatoire aiderait avec le premier. Comme aucun test ne peut prédire ce qui s'est passé auparavant, il ne peut dépendre d'aucun autre test ayant été exécuté auparavant. En changeant l'ordre à chaque exécution, vous trouverez également des tests accidentellement en fonction de l'ordre d'exécution.

Mais si vous changez l'ordre d'exécution en aléatoire, vos tests peuvent également devenir non répétables. Donc, si vous exécutez les tests sur la même machine deux fois, ils peuvent donner des résultats différents. Ce sera probablement parce que vos tests sont couplés d'une manière ou d'une autre. Ils ne devraient pas l'être, mais ils le sont. Il n'y a pas de moyen facile de gérer ces résultats. Que faites-vous si vous essayez de déployer un logiciel parce que tout était vert tout le temps, mais que dans le test final, vous trouvez par accident le seul ordre d'exécution qui freine un test ? Les tests doivent réussir ou échouer et ils doivent le faire à plusieurs reprises. (Ou bien quelqu'un commencera à ignorer les tests qui échouent et à les réexécuter pour les faire réussir.)

C'est très probablement une partie de ce qui a permis l'implémentation comme mentionné par @ffbit : C'est un compromis pour faire face aux deux problèmes. En rendant la commande imprévisible, ils ont rendu difficile pour quiconque de mettre en œuvre des tests pour l'utiliser. En le rendant déterministe, ils ont veillé à ce que l'exécution des tests aboutisse toujours au même résultat.

Salut @Endron. Votre argument est bon, mais veuillez regarder de plus près dans l'implémentation --order random option Rspec --order rand:3455 . Il garantit que les tests seront exécutés dans le même ordre.

Citer:

Lorsque vous utilisez --order random , RSpec imprime le nombre aléatoire qu'il a utilisé pour amorcer le randomiseur. Lorsque vous pensez avoir trouvé un bogue de dépendance à l'ordre, vous pouvez transmettre la graine et l'ordre restera cohérent :

--order rand:3455

Ceci est un exemple d'exécution (vous pouvez voir que la graine est affichée en ligne de commande): https://travis-ci.org/coi-gov-pl/puppet-jboss/jobs/81936397#L556

Je viens de soumettre une pull request ajoutant cette fonctionnalité.
Comme c'est la première fois que je contribue, vos commentaires sont particulièrement importants. Merci!

PS Désolé pour les multiples avis de commit. Étant relativement nouveau sur GitHub, je ne savais pas que le simple fait de pousser vers mon propre référentiel lui permettrait de le faire.

Je pense que cela peut aussi être fait avec PR #1130. La graine peut être définie en externe par les plugins Maven et Gradle

Nous avons vraiment besoin d'un moyen simple en tant que nouvelle MethodSorters et éventuellement en tant que propriété système globale (RANDOM éventuellement mais DEFAULT par défaut) pour avoir un ordre totalement aléatoire pour tout test n'utilisant pas explicitement l'un des MethodSorters existants
Cela aidera beaucoup à trouver tous ces tests mal écrits dans toutes les applications héritées (ou nouvelles) sur lesquelles nous travaillons.

Je voudrais dire que si vous utilisez Maven pour exécuter vos tests, vous pourriez être intéressé par ce PR https://github.com/apache/maven-surefire/pull/112 to Surefire/Failsafe plugin pour introduire la randomisation des tests au niveau de la classe avec des graines.

Merci @cardil Cela me sera certainement utile, mais lorsque ticket devrait ajouter un ordre d'exécution dans Junit 5.3

Cette page vous a été utile?
0 / 5 - 0 notes