Junit4: Wirklich zufälliger Testauftrag mit Möglichkeit für extern gegebenes Saatgut

Erstellt am 26. Aug. 2015  ·  9Kommentare  ·  Quelle: junit-team/junit4

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.

Ref: 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>

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/

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:

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

Alle 9 Kommentare

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:

  1. Tests je nach Ausführungsreihenfolge
  2. Nicht wiederholbare Tests

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

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen