6

我正在尝试解决两个 ScalaCheck (+ specs2) 问题:

  1. 有没有办法改变 ScalaCheck 生成的案例数量?

  2. 如何生成包含一些 Unicode 字符的字符串?

例如,我想生成大约 10 个包含字母数字和 Unicode 字符的随机字符串。然而,这段代码总是生成 100 个随机字符串,并且它们是严格基于字母字符的:

"make a random string" in {
    def stringGenerator = Gen.alphaStr.suchThat(_.length < 40)
    implicit def randomString: Arbitrary[String] = Arbitrary(stringGenerator)

    "the string" ! prop { (s: String) => (s.length > 20 && s.length < 40) ==> { println(s); success; } }.setArbitrary(randomString)
}

编辑

我才意识到还有一个问题:

  1. ScalaCheck 经常在没有生成 100 个测试用例的情况下放弃

当然,我不想要 100,但显然我的代码正试图生成一组过于复杂的规则。上次运行时,我看到“47 次测试后放弃”。

4

1 回答 1

13

“在 47 次测试后放弃”错误意味着您的条件(包括suchThat谓词和==>部分)过于严格。幸运的是,将它们烘焙到您的生成器中通常并不难,在您的情况下,您可以编写类似这样的内容(这也解决了选择任意字符的问题,而不仅仅是字母数字字符):

val stringGen: Gen[String] = Gen.chooseNum(21, 40).flatMap { n =>
  Gen.buildableOfN[String, Char](n, arbitrary[Char])
}

在这里,我们在所需范围内选择任意长度,然后选择该数量的任意字符并将它们连接成一个字符串。

您还可以增加maxDiscardRatio参数:

import org.specs2.scalacheck.Parameters
implicit val params: Parameters = Parameters(maxDiscardRatio = 1024)

但这通常不是一个好主意——如果你丢弃了大部分生成的值,你的测试将花费更长的时间,并且重构你的生成器通常会更干净、更快。

您还可以通过设置适当的参数来减少测试用例的数量:

implicit val params: Parameters = Parameters(minTestsOk = 10)

但同样,除非您有充分的理由这样做,否则我建议您相信默认设置。

于 2015-05-21T08:36:11.213 回答