scalacheck 中生成器的大小

发布于 2024-09-18 09:14:18 字数 698 浏览 5 评论 0原文

scalacheck 项目的 UserGuide 提到了大小的生成器。解释代码

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 

您能否解释一下我错过了什么,并给我一些如何在测试代码中使用它们的示例?

UserGuide of scalacheck project mentioned sized generators. The explanation code

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))
}

explained nothing for me. After some exploration I understood that length of generated sequence does not depend on actual size of generator (there is resize method in Gen object that "Creates a resized version of a generator" according to javadoc (maybe that means something different?)).

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 

Could you explain me what had I missed and give me some examples how you use them in testing code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凌乱心跳 2024-09-25 09:14:18

vectorOf(现在已替换为 listOf)生成的列表,其大小(线性)取决于 ScalaCheck 在计算生成器时设置的大小参数。当 ScalaCheck 测试属性时,它会为每个测试增加此大小参数,从而导致使用越来越大的列表来测试属性(如果使用 listOf)。

如果您仅通过以嵌套方式使用 listOf 生成器来创建矩阵生成器,您将获得大小取决于大小参数的平方的矩阵。因此,当在属性中使用此类生成器时,您可能会得到非常大的矩阵,因为 ScalaCheck 会增加每次测试运行的大小参数。但是,如果您按照 ScalaCheck 用户指南中的方式使用 resize 生成器组合器,则最终矩阵大小线性取决于大小参数,从而在测试属性时获得更好的性能。

您实际上不必经常使用 resize 生成器组合器。如果您需要生成受某个特定大小限制的列表,最好执行如下示例所示的操作,因为不能保证 listOf/ containerOf生成器确实按照您期望的方式使用大小参数。

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

The vectorOf (which now is replaced with listOf) generates lists with a size that depends (linearly) on the size parameter that ScalaCheck sets when it evaluates a generator. When ScalaCheck tests a property it will increase this size parameter for each test, resulting in properties that are tested with larger and larger lists (if listOf is used).

If you create a matrix generator by just using the listOf generator in a nested fashion, you will get matrices with a size that depends on the square of the size parameter. Hence when using such a generator in a property you might end up with very large matrices, since ScalaCheck increases the size parameter for each test run. However, if you use the resize generator combinator in the way it is done in the ScalaCheck User Guide, your final matrix size depend linearly on the size parameter, resulting in nicer performance when testing your properties.

You should really not have to use the resize generator combinator very often. If you need to generate lists that are bounded by some specific size, it's much better to do something like the example below instead, since there is no guarantee that the listOf/ containerOf generators really use the size parameter the way you expect.

def genBoundedList(maxSize: Int, g: Gen[T]): Gen[List[T]] = {
  Gen.choose(0, maxSize) flatMap { sz => Gen.listOfN(sz, g) }
}
余生共白头 2024-09-25 09:14:18

您使用的 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))

The vectorOf method that you use is deprecated , and you should use the listOf method. This generates a list of random length where the maximum length is limited by the size of the generator. You should therefore resize the generator that
actually generates the actual list if you want control over the maximum elements that are generated:


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))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文