Размерные генераторы в scalacheck
UserGuide в названных размерах генераторах типа 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))
}
ничего не объяснил для меня. После некоторого исследования я понял, что длина сгенерированной последовательности не зависит от фактического размера генератора (существует метод изменения размера в объекте Gen, который "создает измененную версию генератора" в соответствии с javadoc (может быть, это означает что-то другое?)).
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
Не могли бы вы объяснить мне, что я пропустил, и дать мне несколько примеров того, как вы используете их при тестировании кода?
Ответы
Ответ 1
Используемый метод vectorOf
устарел, и вы должны использовать метод listOf. Это генерирует список случайной длины, где максимальная длина ограничена размером генератора. Поэтому вы должны изменить размер генератора, который
фактически генерирует фактический список, если вы хотите контролировать максимальные генерируемые элементы:
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))
Ответ 2
vectorOf
(который теперь заменяется на listOf
) генерирует списки с размером, который зависит (линейно) от параметра размера, который ScalaCheck устанавливает, когда он оценивает генератор. Когда ScalaCheck проверяет свойство, он увеличит этот параметр размера для каждого теста, в результате чего будут тестироваться свойства с более крупными и большими списками (если используется listOf
).
Если вы создаете генератор матрицы, просто используя генератор listOf
вложенным образом, вы получите матрицы с размером, который зависит от квадрата параметра размера. Следовательно, при использовании такого генератора в свойстве вы можете получить очень большие матрицы, поскольку ScalaCheck увеличивает параметр размера для каждого тестового прогона. Однако, если вы используете комбинатор генератора resize
таким образом, как это делается в Руководстве пользователя ScalaCheck, конечный размер матрицы зависит от линейного параметра размера, что приводит к лучшей производительности при тестировании ваших свойств.
Вам действительно не нужно часто использовать комбинатор генератора resize
. Если вам нужно создавать списки, ограниченные определенным размером, гораздо лучше сделать что-то вроде приведенного ниже примера, так как нет гарантии, что генераторы listOf
/containerOf
действительно используют параметр размера так, как вы ожидаете.
def genBoundedList(maxSize: Int, g: Gen[T]): Gen[List[T]] = {
Gen.choose(0, maxSize) flatMap { sz => Gen.listOfN(sz, g) }
}