Standardmäßig führt junit den Test in der Standardreihenfolge aus, die auf dem Hashcode des Methodennamens basiert. In Java ändern sich Hashcodes von Strings zwischen den Ausführungen nicht, daher ist die Reihenfolge zufällig, aber für einen bestimmten Computer konstant. Das kann zu unvorhersehbaren Fehlern führen.
$ 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>
Um diese Verzauberung zu beheben, sollte es eine wirklich zufällige Reihenfolge geben, die im Testfall explizit mit @FixMethodOrder
.
Ich schlage vor, die Implementierung der zufälligen Option Rspec --order
zu befolgen. Es macht tatsächlich eine zufällige Reihenfolge für die Ausführung, aber der dafür verwendete Seed wird angezeigt und in Berichten protokolliert. Dies gibt Entwicklern die Möglichkeit, dieselbe Ausführung mit --order rand:3455
auszuführen. Es garantiert, dass Tests in der gleichen Reihenfolge ausgeführt werden, daher ist es möglich, nach Fehlern in der Ausführungsreihenfolge zu suchen.
Zitieren:
Wenn Sie --order random verwenden, gibt RSpec die Zufallszahl aus, die es verwendet hat, um den Randomizer zu setzen. Wenn Sie glauben, einen Fehler in der Reihenfolgenabhängigkeit gefunden zu haben, können Sie den Seed weitergeben und die Reihenfolge bleibt konsistent:
--Bestellrand :3455
Beispielausführung:
$ 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
Zufällige Rspec-Referenz: http://blog.davidchelimsky.net/blog/2012/01/04/rspec-28-is-released/
Darf ich Knuth Shuffle vorschlagen, um die Laufreihenfolge zu bestimmen?
die Info-
https://en.wikipedia.org/wiki/Fisher –Yates_shuffle
Quellcode-
http://algs4.cs.princeton.edu/11model/Knuth.java.html
Aus der Testausführungsreihenfolge
JUnit legt die Ausführungsreihenfolge von Testmethodenaufrufen nicht fest. Bisher wurden die Methoden einfach in der von der Reflection-API zurückgegebenen Reihenfolge aufgerufen. Die Verwendung der JVM-Reihenfolge ist jedoch unklug, da die Java-Plattform keine bestimmte Reihenfolge vorgibt und JDK 7 tatsächlich eine mehr oder weniger zufällige Reihenfolge zurückgibt. Natürlich würde gut geschriebener Testcode keine Reihenfolge annehmen, aber einige tun es, und ein vorhersehbarer Fehler ist auf bestimmten Plattformen besser als ein zufälliger Fehler.
Ab Version 4.11 verwendet JUnit standardmäßig eine deterministische, aber nicht vorhersagbare Reihenfolge (MethodSorters.DEFAULT). Um die Testausführungsreihenfolge zu ändern, kommentieren Sie einfach Ihre Testklasse mit
@FixMethodOrder(MethodSorters.JVM): Belässt die Testmethoden in der von der JVM zurückgegebenen Reihenfolge. Diese Reihenfolge kann von Lauf zu Lauf variieren.
@FixMethodOrder(MethodSorters.NAME_ASCENDING): Sortiert die Testmethoden nach Methodennamen in lexikografischer Reihenfolge.
Das Problem dabei ist, dass es eigentlich zwei Testgerüche gibt, die miteinander verbunden sind:
Tests in eine wirklich zufällige Reihenfolge zu bringen, würde beim ersten helfen. Da kein Test vorhersagen kann, was vorher passiert ist, kann er sich nicht darauf verlassen, dass ein anderer Test zuvor durchgeführt wurde. Durch Ändern der Reihenfolge bei jedem Durchlauf würden Sie je nach Ausführungsreihenfolge auch versehentlich Tests finden.
Aber wenn Sie die Ausführungsreihenfolge auf zufällig ändern, können Ihre Tests auch nicht wiederholbar werden. Wenn Sie die Tests also zweimal auf demselben Computer ausführen, können sie zu unterschiedlichen Ergebnissen führen. Dies wird höchstwahrscheinlich daran liegen, dass Ihre Tests in irgendeiner Weise gekoppelt sind. Sie sollten nicht sein, aber sie sind. Es gibt keinen einfachen Weg, mit diesen Ergebnissen umzugehen. Was tun Sie, wenn Sie versuchen, Software bereitzustellen, weil die ganze Zeit alles grün war, Sie aber im letzten Test versehentlich die eine Ausführungsreihenfolge finden, die einen Test bremst? Tests müssen entweder bestehen oder fehlschlagen und dies müssen sie wiederholt tun. (Oder sonst beginnt jemand, fehlgeschlagene Tests zu ignorieren und führt sie einfach erneut aus, um sie zum Bestehen zu bringen.)
Dies ist höchstwahrscheinlich ein Teil dessen, was die von @ffbit erwähnte
Hallo @Endron. Ihr Punkt ist gut, aber schauen Sie sich bitte die Implementierung der Option Rspec --order random
genauer an. Es macht tatsächlich eine zufällige Reihenfolge für die Ausführung, aber der dafür verwendete Seed wird angezeigt und in Berichten protokolliert. Dies gibt Entwicklern die Möglichkeit, dieselbe Ausführung mit --order rand:3455
auszuführen. Es garantiert, dass Tests in der gleichen Reihenfolge ausgeführt werden.
Zitieren:
Wenn Sie
--order random
, gibt RSpec die Zufallszahl aus, die es verwendet hat, um den Randomizer zu setzen. Wenn Sie glauben, einen Fehler in der Reihenfolgenabhängigkeit gefunden zu haben, können Sie den Seed weitergeben und die Reihenfolge bleibt konsistent:
--order rand:3455
Dies ist eine Beispielausführung (Sie können sehen, dass der Seed in der Befehlszeile angezeigt wird): https://travis-ci.org/coi-gov-pl/puppet-jboss/jobs/81936397#L556
Ich habe gerade eine Pull-Anfrage eingereicht, um diese Funktion hinzuzufügen.
Da dies mein erster Beitrag ist, ist Ihr Feedback besonders wichtig. Vielen Dank!
PS Entschuldigung für die mehrfachen Commit-Benachrichtigungen. Da ich relativ neu bei GitHub bin, war mir nicht klar, dass das bloße Verschieben auf mein eigenes Repo dies tun würde.
Ich denke, dass dies auch mit PR #1130 möglich ist. Der Seed kann extern durch Maven- und Gradle-Plugins gesetzt werden
Wir brauchen wirklich einen einfachen Weg als neuen MethodSorters
Wert und möglicherweise als globale Systemeigenschaft (möglicherweise RANDOM, aber standardmäßig DEFAULT), um eine völlig zufällige Reihenfolge für jeden Test zu haben, der nicht explizit eines der vorhandenen MethodSorters
. Fügen Sie nach Bedarf automatisches Seeding hinzu, um eine wirkliche Zufälligkeit ohne spezielle Einstellungen zu erhalten.
Dies wird eine Menge bei der Suche nach all diesen schlecht schriftlichen Prüfungen in alle hilft das Erbe (oder neu) wir auf Anwendungen arbeiten.
Ich möchte sagen, dass Sie an diesem PR https://github.com/apache/maven-surefire/pull/112 zum Surefire/Failsafe-Plugin interessiert sein könnten, wenn Sie Maven verwenden, um Ihre Tests durchzuführen, um die Randomisierung von Tests auf Klassenebene einzuführen mit Samen.
Danke @cardil Das wird sicherlich nützlich sein, aber wenn ich den Test in meiner IDE ausführe, Ticket eine Ausführungsreihenfolge in Junit 5.3 hinzufügen sollte
Hilfreichster Kommentar
Hallo @Endron. Ihr Punkt ist gut, aber schauen Sie sich bitte die Implementierung der Option Rspec
--order random
genauer an. Es macht tatsächlich eine zufällige Reihenfolge für die Ausführung, aber der dafür verwendete Seed wird angezeigt und in Berichten protokolliert. Dies gibt Entwicklern die Möglichkeit, dieselbe Ausführung mit--order rand:3455
auszuführen. Es garantiert, dass Tests in der gleichen Reihenfolge ausgeführt werden.Zitieren:
Dies ist eine Beispielausführung (Sie können sehen, dass der Seed in der Befehlszeile angezeigt wird): https://travis-ci.org/coi-gov-pl/puppet-jboss/jobs/81936397#L556