ScalaCheck generators for Cats data types.
2024-07-22
While ScalaCheck is a powerful library that comes with quite some generators already, you need to write your own for your custom types. However I found it problematic that simply deriving generators for Cats “container” data types from existing ones is not included.
But actually the solution is not that complicated. During working on the Smederee I found a solution that works. Here is an example for generating a NonEmptyList:
First we need a generator for an actual NonEmptyList[A]
which of course needs a generator for A
to be in scope (i.e. an Arbitrary[A]
).
given genNel[A](using singleValue: Arbitrary[A]): Gen[NonEmptyList[A]] =
for {
head <- singleValue.arbitrary
tail <- Gen.nonEmptyListOf(singleValue.arbitrary)
} yield NonEmptyList.of(head, tail: _*)
Of course we could have used a Gen.listOf
for the tail because a non-empty list must only have at least one entry but usually it is desired to have more than one value. ;-)
And last but not least we need to provide this automatically for the user:
given [A](using genNel: Gen[NonEmptyList[A]]): Arbitrary[NonEmptyList[A]] = Arbitrary(genNel)
Now we can simply write things like forAll { (as: NonEmptyList[A]) => ... }
and the container will be generated for us if the Given Instances are in scope (e.g. by using something like import my.package.given
).