4

我正在尝试使用 scalacheck 1.6.6 和规范 1.7(scala 2.8.1)创建一个生成(非零长度)合法 unicode 字符串的生成器。

我希望我可以创建像这样的生成器:

object Generators {
  def unicodeChar: Gen[Char] = 
    choose(Math.MIN_CHAR, Math.MAX_CHAR).map(_.toChar).filter(
      c => Character.isDefined(c))
  def unicodeStr: Gen[String] = for(cs <- listOf1(unicodeChar)) yield cs.mkString
}

...然后从规格中使用它们,例如:

import org.specs.Specification
import org.specs.matcher.ScalaCheckMatchers

object CoreSpec extends Specification with ScalaCheckMatchers {        
  "The core" should {    
    "pass trivially" in {
      Generators.unicodeStr must pass((s: String) => s == s)
    }
  }
}

但是,似乎在 unicodeChar 中使用过滤器会导致问题:

Specification "CoreSpec"
  The core should
  x pass trivially
    Gave up after only 64 passed tests. 500 tests were discarded.

如果我从 unicodeChar 中删除过滤器,我的测试会通过,但我稍后会遇到其他问题,因为我的字符串并不总是定义明确的 unicode。

在此先感谢您提供有关如何实现此目标的任何建议。

4

4 回答 4

9

在创建生成器之前尝试过滤掉字符:

val unicodeChar: Gen[Char] = Gen.oneOf((Math.MIN_CHAR to Math.MAX_CHAR).filter(Character.isDefined(_)))

这将更加占用内存,因为在创建生成器时将分配完整的 unicode 字符列表,但只会使用该列表的一个实例,因此这应该不是什么大问题。

于 2010-12-07T17:56:14.800 回答
5

我不知道 2010 年的情况如何,但现在你可以使用Arbitrary

  import org.scalacheck.Arbitrary
  import org.scalacheck.Gen

  val unicodeChar: Gen[Char] = Arbitrary.arbChar.arbitrary
  val unicodeString: Gen[String] = Arbitrary.arbString.arbitrary
于 2016-02-23T12:56:28.260 回答
3

好的,我想通了。这对我有用:

def unicodeChar = Gen((p: Gen.Params) => {
    var c = 0
    do {
      c = util.Random.nextInt(0xFFFF)
    } while (!Character.isDefined(c))
    Some(c.toChar)
  })

其实很简单。我没有得到的是,您可以通过将函数 Gen.Params => T 传递给 Gen.apply() 来创建 T 类型的任意生成器。

于 2010-12-07T17:52:15.737 回答
0

你试过suchThat代替filter吗?

于 2010-12-07T18:42:35.283 回答