2010-09-08 14 views
14

UserGuide del proyecto scalacheck mencionado generadores de tamaño. El código de explicacióngeneradores de tamaño en 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)) 
} 

no me explicaron nada. Después de algunas exploraciones, entendí que la longitud de la secuencia generada no depende del tamaño real del generador (hay un método de cambio de tamaño en el objeto Gen que "Crea una versión redimensionada de un generador" según javadoc (¿quizás eso significa algo diferente?)).

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 

¿Podría explicarme qué había echado de menos y darme algunos ejemplos de cómo los usa en el código de prueba?

Respuesta

9

El método vectorOf que utiliza está en desuso, y debe utilizar el método listOf. Esto genera una lista de longitud aleatoria donde la longitud máxima está limitada por el tamaño del generador. Por lo tanto, usted debe cambiar el tamaño del generador que realmente genera la lista real si desea tener un control sobre los elementos máximos que se generan:


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

El vectorOf (que ahora se reemplaza con listOf) genera listas con un tamaño que depende (linealmente) en el parámetro de tamaño que ScalaCheck establece cuando evalúa un generador. Cuando ScalaCheck prueba una propiedad, aumentará este parámetro de tamaño para cada prueba, dando como resultado propiedades que se prueban con listas cada vez más grandes (si se usa listOf).

Si crea un generador de matriz simplemente usando el generador listOf anidado, obtendrá matrices con un tamaño que depende del cuadrado del parámetro de tamaño. Por lo tanto, cuando se utiliza un generador de este tipo en una propiedad, puede terminar con matrices muy grandes, ya que ScalaCheck aumenta el parámetro de tamaño para cada ejecución de prueba. Sin embargo, si usa el combinador de generador resize tal como se hace en la Guía del usuario de ScalaCheck, su tamaño de matriz final dependerá linealmente del parámetro de tamaño, lo que dará como resultado un mejor rendimiento al probar sus propiedades.

No debería tener que utilizar muy a menudo el combinador de generador resize. Si necesita generar listas que estén limitadas por un tamaño específico, es mejor hacer algo como el siguiente ejemplo, ya que no hay garantía de que los generadores listOf/containerOf realmente utilicen el parámetro de tamaño de la manera esperada.

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

Este es un buen ejemplo, gracias. Muy ilustrativo. –

+1

Esto me llevó a 'Gen.frequency ((10, 2), (5, 3), (1, 1)). FlatMap (Gen.listOfN (_, names))' que era exactamente lo que necesitaba. –

Cuestiones relacionadas