I'm trying to solve two ScalaCheck (+ specs2) problems:
Is there any way to change the number of cases that ScalaCheck generates?
How can I generate strings that contain some Unicode characters?
For example, I'd like to generate about 10 random strings that include both alphanumeric and Unicode characters. This code, however, always generates 100 random strings, and they are strictly alpha character based:
"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)
}
Edit
I just realized there's another problem:
- Frequently, ScalaCheck gives up without generating 100 test cases
Granted I don't want 100, but apparently my code is trying to generate an overly complex set of rules. The last time it ran, I saw "gave up after 47 tests."
The "gave up after 47 tests" error means that your conditions (which include both the suchThat
predicate and the ==>
part) are too restrictive. Fortunately it's often not too hard to bake these into your generator, and in your case you can write something like this (which also addresses the issue of picking arbitrary characters, not just alphanumeric ones):
val stringGen: Gen[String] = Gen.chooseNum(21, 40).flatMap { n =>
Gen.buildableOfN[String, Char](n, arbitrary[Char])
}
Here we pick an arbitrary length in the desired range and then pick that number of arbitrary characters and concatenate them into a string.
You could also increase the maxDiscardRatio
parameter:
import org.specs2.scalacheck.Parameters
implicit val params: Parameters = Parameters(maxDiscardRatio = 1024)
But that's typically not a good idea—if you're throwing away most of your generated values your tests will take longer, and refactoring your generator is generally a lot cleaner and faster.
You can also decrease the number of test cases by setting the appropriate parameter:
implicit val params: Parameters = Parameters(minTestsOk = 10)
But again, unless you have a good reason to do this, I'd suggest trusting the defaults.