2012-09-28 23 views
14

Chciałbym, aby moje testy właściwości ScalaCheck w moim zestawie testów specs2 były tymczasowo deterministyczne, aby ułatwić debugowanie. Obecnie za każdym razem, gdy ponownie uruchamiam pakiet testowy, można wygenerować różne wartości, co sprawia, że ​​debugowanie jest frustrujące, ponieważ nie wiesz, czy zmiana obserwowanych zachowań jest spowodowana zmianami w kodzie lub po prostu generowaniem różnych danych.Przeprowadź testy ScalaCheck deterministyczne

Jak mogę to zrobić? Czy istnieje oficjalny sposób ustawiania losowego materiału siewnego używanego przez ScalaCheck?

Używam sbt do uruchomienia zestawu testów.

Bonus pytanie: Czy istnieje oficjalny sposób wydruku losowych nasion używany przez ScalaCheck, tak aby można było odtworzyć nawet niedeterministycznego próbny?

+0

Skąd się biorą te zmienne dane? A db? Serwer ? –

+0

@ BrianAgnew Nie, jest losowo generowany przez 'ScalaCheck'. –

Odpowiedz

10

Jeśli używasz czystych właściwości ScalaCheck, powinieneś być w stanie korzystać z klasy Test.Params zmienić instancję java.util.Random który jest używany i podać swój własny, który zawsze zwraca ten sam zestaw wartości:

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

[updated]

właśnie opublikował nowy specs2-1.12.2-SNAPSHOT, gdzie można użyć następującej składni, aby określić losowy generator:

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

Co masz na myśli mówiąc "używając czystych właściwości ScalaCheck"? Masz na myśli, nie używając żadnych specs2 tam? –

+0

Mam na myśli używanie specyfikacji ScalaCheck: 'obiekt StringSpecification rozszerza właściwości (" String ")', jak pokazano w ScalaCheck UserGuide: https://github.com/rickynils/scalacheck/wiki/User-Guide – Eric

1

Zgodnie z ogólną zasadą, podczas testowania na niedeterministycznych danych wejściowych powinieneś próbować echo lub zapisać te wejścia gdzieś, gdy wystąpi awaria.

Jeśli dane są małe, można je uwzględnić w etykiecie lub komunikacie o błędzie wyświetlanym użytkownikowi; Na przykład, w teście xUnit stylu: (ponieważ jestem nowy w składni Scala)

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

Jeśli dane są duże, na przykład wygenerowany automatycznie DB, może też przechowywać je w sposób nie- niestabilna lokalizacja (np./tmp z nazwą znacznika czasu) lub wyświetla ziarno użyte do wygenerowania.

Kolejny krok jest ważny: weź tę wartość, nasienie lub cokolwiek i dodaj do swoich deterministycznych testów regresji, aby od tej pory była sprawdzana za każdym razem.

Mówisz, że chcesz, aby ScalaCheck był deterministyczny "tymczasowo" do odtworzenia tego problemu; Twierdzę, że znalazłeś powikłaną skrzynkę na krawędzi, która nadaje się do testów jednostkowych (być może po ręcznym uproszczeniu).

0

Dla scalacheck-1.12 ta konfiguracja działa:

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

Dla scalacheck-1.13 to już nie działa, ponieważ metoda RNG jest usuwany. jakieś pomysły?