Building useful Scalacheck Generators

Manuel Rodríguez
2 min readFeb 8, 2020

--

Scalacheck Generators are an incredible powerful tool, but for some reason they are barely used in production environments. I’ve seen several talks and articles about how cool they are but they only show toy examples, so it’s probably difficult to imagine all the possibilities they offer. In fact, all the code that I have written at Twilio is tested using generators, without a single test using hand-made input data!

Non-related picture that Medium suggested when I searched for “testing”. Photo by nrd on Unsplash

In this article I’ll show some tools that will help you build more complex generators, useful to test real world logic. Note that it is not intended to be a full explanation on generators or why they are great. If you are looking for that, a good introduction could be these exercises by 47 degrees.

In the first example we’ll see how to compose generators. As you know, Gen is a Monad, so we can create smaller ones and then use a for comprehension to compose. Here we are building a URL.

Also, note that we are using map to change the return type. In line 2, we are replacing a List[String] with a single String concatenating the elements with a dot, and in line 4 we do the same using slash as separator.

The yield section can also have some logic. For example, this generator generates a pair of ordered positive numbers

You can create generators for your own types, not only use the default ones. For example, we can generate random elements of Person class this way

In this example there is a generator with an optional parameter. This way, you can determine which parameters are completely random and which ones are fixed depending on the test.

Here we could have just used fold(Gen.alphaNumStr)(Gen.const) on line 5, but I made the parameter explicit for the sake of clarity

This can go even further, and use Generators as input parameters for other generators. In this case we do that and also include a default value. Also, as the account number is a string with a particular characteristic (22 digit String) we generate it separately

And of course, the next level of complexity includes higher order type generators. In this case we have a generator that creates key-value pairs, and then use it to generate Json inputs for an endpoint.

As the -from my limited knowledge- most abstract layer, you can create libraries using this kind of generators and then instantiate them with the ones you need. There is an example in a previous post, Property testing of isomorphisms: way easier than you it sounds!

As you can see, you can create generators for everything you need to test you application with little effort.

--

--

Manuel Rodríguez

Developer at New Relic. This is where I keep the cool stuff that I learn in my free time