问题
I'm trying to create a generator that produces (non-zero-length) legal unicode strings, with scalacheck 1.6.6 and specs 1.7 (scala 2.8.1).
I hoped I could just create generators like:
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
}
...then use them from specs like:
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)
}
}
}
But, it seems that using filter in unicodeChar causes a problem:
Specification "CoreSpec"
The core should
x pass trivially
Gave up after only 64 passed tests. 500 tests were discarded.
If I remove the filter from unicodeChar, my test passes, but I run into other problems later, since my strings are not always well-defined unicode.
Thanks in advance for any suggestions on how to achieve this.
回答1:
Try filtering out the characters before creating the generator:
val unicodeChar: Gen[Char] = Gen.oneOf((Math.MIN_CHAR to Math.MAX_CHAR).filter(Character.isDefined(_)))
It will be more memory intensive, since the complete list of unicode characters will be allocated when the generator is created, but only one instance of that list will be used so it shouldn't be a big problem.
回答2:
I don't know how it was in 2010, but nowadays you can use Arbitrary
:
import org.scalacheck.Arbitrary
import org.scalacheck.Gen
val unicodeChar: Gen[Char] = Arbitrary.arbChar.arbitrary
val unicodeString: Gen[String] = Arbitrary.arbString.arbitrary
回答3:
Ok, I figured it out. This is what works for me:
def unicodeChar = Gen((p: Gen.Params) => {
var c = 0
do {
c = util.Random.nextInt(0xFFFF)
} while (!Character.isDefined(c))
Some(c.toChar)
})
Pretty simple, actually. What I didn't get is that you can create an arbitrary generator of type T by passing a function Gen.Params => T to Gen.apply().
回答4:
Have you tried suchThat
instead of filter
?
来源:https://stackoverflow.com/questions/4379055/generating-arbitrary-legal-unicode-character-with-scalacheck