2012-09-28 10 views
14

Ich möchte meine ScalaCheck-Eigenschaft Tests in meiner Specs2-Test-Suite vorübergehend deterministisch machen, um das Debuggen zu erleichtern. Im Moment könnten bei jedem erneuten Ausführen der Testsuite andere Werte generiert werden, was das Debugging frustrierend macht, weil Sie nicht wissen, ob eine Änderung des beobachteten Verhaltens durch Ihre Codeänderungen oder nur durch die Generierung anderer Daten verursacht wird.Machen Sie ScalaCheck Tests deterministisch

Wie kann ich das tun? Gibt es eine offizielle Möglichkeit, den von ScalaCheck verwendeten Zufallssatz festzulegen?

Ich verwende , um die Testsuite zu starten.

Bonus Frage: Gibt es einen offiziellen Weg zu Ausdruck der Zufall Samt von Scalacheck verwendet, so dass Sie auch einen nicht-deterministischen Testlauf wiedergeben können?

+0

Woher kommen diese wechselnden Daten? Eine db? Ein Server ? –

+0

@BrianAgnew Nein, es wird zufällig von 'ScalaCheck' generiert. –

Antwort

10

Wenn Sie reine Scalacheck Eigenschaften verwenden, sollten Sie in der Lage sein, die Test.Params Klasse zu verwenden, um die java.util.Random Instanz zu ändern, die verwendet wird, und Ihre eigenen zu schaffen, die immer die gleichen Werte zurück:

def check(params: Test.Parameters, p: Prop): Test.Result

[aktualisiert]

I veröffentlichte gerade einen neuen specs2-1.12.2-snapshot, wo Sie die folgende Syntax verwenden, können Sie Ihren Zufallsgenerator angeben:

case class MyRandomGenerator() extends java.util.Random { 
    // implement a deterministic generator 
} 

"this is a specific property" ! prop { (a: Int, b: Int) => 
    (a + b) must_== (b + a) 
}.set(MyRandomGenerator(), minTestsOk -> 200, workers -> 3) 
+0

Was meinen Sie mit "Verwendung von reinen ScalaCheck-Eigenschaften"? Meinst du, du verwendest dort keine specs2-Sachen? –

+0

Ich meine eine ScalaCheck Spezifikation: 'object StringSpecification erweitert Eigenschaften (" String ")', wie im ScalaCheck UserGuide gezeigt: https://github.com/rickynils/scalacheck/wiki/User-Guide – Eric

1

Als allgemeine Regel, wenn Sie auf nicht-deterministischen Eingaben testen, sollten Sie versuchen, diese Eingaben irgendwo zu wiederholen oder zu speichern, wenn ein Fehler auftritt.

Wenn die Daten klein sind, können Sie sie in das Etikett oder die Fehlermeldung einfügen, die dem Benutzer angezeigt wird. beispielsweise in einem xUnit-Stil-Test: (da ich zu Scala Syntax bin neu)

testLength(String x) { 
    assert(x.length > 10, "Length OK for '" + x + "'"); 
} 

Wenn die Daten groß ist, zum Beispiel ein automatisch generierter DB, können Sie entweder speichern sie in einem nicht flüchtiger Ort (zB./tmp mit einem Namen mit Zeitstempel) oder zeigen Sie den Samen an, um ihn zu erzeugen.

Der nächste Schritt ist wichtig: nimm diesen Wert oder Startwert oder was auch immer, und füge ihn zu deinen deterministischen Regressionstests hinzu, so dass er von nun an jedes Mal überprüft wird.

Sie sagen, Sie möchten ScalaCheck deterministisch "vorübergehend" machen, um dieses Problem zu reproduzieren; Ich sage, dass Sie einen Buggy-Edge-Case gefunden haben, der gut geeignet ist, um ein Komponententest zu werden (vielleicht nach manueller Vereinfachung).

0

Für scalacheck-1.12 diese Konfiguration gearbeitet:

new Test.Parameters { 
    override val rng = new scala.util.Random(seed) 
} 

Für scalacheck-1.13 es nicht mehr funktioniert, da die RNG-Methode entfernt wird. Irgendwelche Gedanken?

Verwandte Themen