2010-09-08 21 views
14

UserGuide z projektu skalacheck wspomnianych wielkości generatorów. Kod wyjaśnianiawielkości generatory w scalacheck

def matrix[T](g:Gen[T]):Gen[Seq[Seq[T]]] = Gen.sized {size => 
val side = scala.Math.sqrt(size).asInstanceOf[Int] //little change to prevent compile-time exception 
Gen.vectorOf(side, Gen.vectorOf(side, g)) 
} 

nic mi nie wyjaśnił. Po kilku eksploracjach zrozumiałem, że długość wygenerowanej sekwencji nie zależy od rzeczywistego rozmiaru generatora (w obiekcie Gen istnieje metoda zmiany rozmiaru, która "tworzy zmienioną wersję generatora" zgodnie z javadoc (może to oznacza coś innego?)).

val g = Gen.choose(1,5) 
val g2 = Gen.resize(15, g) 
println(matrix(g).sample) // (1) 
println(matrix(g2).sample) // (2) 
//1,2 produce Seq with same length 

Czy mógłbyś wyjaśnić mi, co przeoczyłem i podać kilka przykładów, jak używasz ich w testowaniu kodu?

Odpowiedz

9

Stosowana metoda vectorOf jest przestarzała i należy użyć metody listOf. Generuje to listę losowej długości, w której maksymalna długość jest ograniczona przez wielkość generatora. Dlatego należy zmienić rozmiar generator, który faktycznie generuje rzeczywisty listy jeśli chcesz kontrolę nad maksymalną elementów, które są generowane:


scala> val g1 = Gen.choose(1,5) 
g1: org.scalacheck.Gen[Int] = Gen() 

scala> val g2 = Gen.listOf(g1) 
g2: org.scalacheck.Gen[List[Int]] = Gen() 

scala> g2.sample 
res19: Option[List[Int]] = Some(List(4, 4, 4, 4, 2, 4, 2, 3, 5, 1, 1, 1, 4, 4, 1, 1, 4, 5, 5, 4, 3, 3, 4, 1, 3, 2, 2, 4, 3, 4, 3, 3, 4, 3, 2, 3, 1, 1, 3, 2, 5, 1, 5, 5, 1, 5, 5, 5, 5, 3, 2, 3, 1, 4, 3, 1, 4, 2, 1, 3, 4, 4, 1, 4, 1, 1, 4, 2, 1, 2, 4, 4, 2, 1, 5, 3, 5, 3, 4, 2, 1, 4, 3, 2, 1, 1, 1, 4, 3, 2, 2)) 

scala> val g3 = Gen.resize(10, g2) 
g3: java.lang.Object with org.scalacheck.Gen[List[Int]] = Gen() 

scala> g3.sample 
res0: Option[List[Int]] = Some(List(1)) 

scala> g3.sample 
res1: Option[List[Int]] = Some(List(4, 2)) 

scala> g3.sample 
res2: Option[List[Int]] = Some(List(2, 1, 2, 4, 5, 4, 2, 5, 3)) 
18

vectorOf (który jest teraz zastąpiony listOf) generuje list o rozmiarze, który zależy (liniowo) na parametrze wielkości, który ustawia ScalaCheck, gdy ocenia generator. Gdy ScalaCheck przetestuje właściwość, zwiększy ona ten parametr wielkości dla każdego testu, czego rezultatem będą właściwości, które są testowane na większych i większych listach (jeśli użyto listOf).

Jeśli utworzysz generator macierzy za pomocą generatora listOf w trybie zagnieżdżonym, otrzymasz macierz o rozmiarze zależnym od kwadratu parametru wielkości. Stąd przy korzystaniu z takiego generatora w obiekcie może pojawić się bardzo duża macierz, ponieważ ScalaCheck zwiększa parametr wielkości dla każdego testu. Jeśli jednak używasz kombinator generatora resize w sposób, w jaki jest to wykonywane w Podręczniku użytkownika ScalaCheck, ostateczny rozmiar macierzy zależy liniowo od parametru wielkości, co zapewnia lepszą wydajność podczas testowania właściwości.

Bardzo często nie powinno się używać generatora generatora resize. Jeśli potrzebujesz wygenerować listy, które są ograniczone określonym rozmiarem, znacznie lepiej jest zrobić coś takiego jak przykład poniżej, ponieważ nie ma gwarancji, że generatory listOf/containerOf rzeczywiście używają parametru rozmiaru w sposób, jakiego oczekujesz.

def genBoundedList(maxSize: Int, g: Gen[T]): Gen[List[T]] = { 
    Gen.choose(0, maxSize) flatMap { sz => Gen.listOfN(sz, g) } 
} 
+0

To jest bardzo dobry przykład, dzięki. Bardzo ilustracyjny. –

+1

To doprowadziło mnie do "Gen.frequency ((10, 2), (5, 3), (1, 1)). FlatMap (Gen.listOfN (_, nazwy))", który był dokładnie tym, czego potrzebowałem! –

Powiązane problemy