使用scalacheck生成任意(合法)Unicode字符?

时间:2010-12-07 16:32:58

标签: scala specs scalacheck

我正在尝试使用scalacheck 1.6.6和specs 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 个答案:

答案 0 :(得分:8)

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

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

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

答案 1 :(得分:3)

我不知道2010年是怎么回事,但现在你可以使用Arbitrary

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

  val unicodeChar: Gen[Char] = Arbitrary.arbChar.arbitrary
  val unicodeString: Gen[String] = Arbitrary.arbString.arbitrary

答案 2 :(得分:2)

好的,我明白了。这对我有用:

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

实际上非常简单。我没有得到的是你可以通过传递函数Gen.Params =&gt;创建一个T类型的任意生成器。 T到Gen.apply()。

答案 3 :(得分:0)

您是否尝试过suchThat而不是filter