2012-09-28 12 views
14

Vorrei rendere i miei test delle proprietà di ScalaCheck nella mia suite di test specs2, temporaneamente, per facilitare il debugging. In questo momento, potrebbero essere generati valori diversi ogni volta che rieseguo la suite di test, il che rende frustrante il debug, perché non si sa se un cambiamento nel comportamento osservato è causato dalle modifiche al codice o semplicemente da dati diversi generati.Effettua i test di ScalaCheck deterministici

Come posso fare questo? Esiste un modo ufficiale per impostare il seme casuale utilizzato da ScalaCheck?

Sto usando sbt per eseguire la suite di test. domanda

Bonus: Esiste un modo ufficiale per stampare il seme casuale usata da ScalaCheck, in modo da poter riprodurre anche un test non-deterministico?

+0

Da dove provengono questi dati mutevoli? Un db? Un server? –

+0

@BrianAgnew No, è generato casualmente da 'ScalaCheck'. –

risposta

10

Se stai usando le proprietà ScalaCheck puri, si dovrebbe essere in grado di utilizzare la classe Test.Params a modificare l'istanza java.util.Random che viene utilizzato e fornire il proprio, che restituisce sempre lo stesso insieme di valori:

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

[aggiornato]

ho appena pubblicato un nuovo specs2-1.12.2-SNAPSHOT dove è possibile utilizzare la seguente sintassi per specificare il generatore di numeri casuali:

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

Cosa intendi con "usare le proprietà di ScalaCheck"? Intendi, non usare nessuna roba specs2 lì dentro? –

+0

Voglio dire usando una specifica di ScalaCheck: 'object StringSpecification estende Properties (" String ")', come mostrato nella guida utente di ScalaCheck: https://github.com/rickynils/scalacheck/wiki/User-Guide – Eric

1

Come regola generale, quando si esegue il test su input non deterministici, è necessario provare a echo o salvare tali input da qualche parte in caso di errore.

Se i dati sono piccoli, è possibile includerli nell'etichetta o nel messaggio di errore che viene visualizzato all'utente; per esempio, in una prova in stile xUnit: (dato che sono nuovi per la sintassi Scala)

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

Se i dati sono di grandi dimensioni, ad esempio un DB generato automaticamente, si potrebbe o conservarlo in un non- posizione volatile (ad esempio/tmp con un nome data/ora) o mostra il seme utilizzato per generarlo.

Il passaggio successivo è importante: prendere quel valore, o seed, o qualsiasi altra cosa, e aggiungerlo ai test di regressione deterministica, in modo che venga controllato ogni volta da ora in poi.

Si dice che si desidera rendere "temporaneamente" deterministico il parametro ScalaCheck per riprodurre questo problema; Dico che hai trovato un buggy edge-case che è adatto per diventare un test unitario (magari dopo una semplificazione manuale).

0

Per scalacheck-1.12 questa configurazione ha funzionato:

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

Per scalacheck-1.13 non funziona più in quanto il metodo RNG è stato rimosso. qualche idea?

Problemi correlati