【问题标题】:Generating arbitrary (legal) Unicode character with scalacheck?使用 scalacheck 生成任意(合法)Unicode 字符?
【发布时间】:2011-05-21 17:06:28
【问题描述】:

我正在尝试使用 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。

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

【问题讨论】:

  • 如果我不使用 Specs 似乎会更容易一些,并提供一个新的隐式 Params 实例。但这只是治标不治本,并不能真正解决根本原因。

标签: scala specs scalacheck


【解决方案1】:

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

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

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

【讨论】:

  • 啊,有道理。谢谢!
  • 这里有一个替代方案:val unicodeChar = Gen.choose(Char.MinValue, Char.MaxValue).filter(Character.isDefined)
【解决方案2】:

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

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

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

【讨论】:

    【解决方案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 类型的任意生成器。

    【讨论】:

      【解决方案4】:

      您是否尝试过suchThat 而不是filter

      【讨论】:

      • 在进一步阅读后我确实尝试过;它有相同的症状。
      • 其实suchThat只是过滤器的一个包装器:def suchThat(p: T => Boolean): Gen[T] = filter(p)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-28
      • 2013-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多