Your own property based testing framework — Part 1: Generators

Nicolas Dubien
3 min readJul 3, 2020

--

While understanding the internals of each tool is not required to use them properly, sometimes I personally feel the need to dig a bit into the tools I am using regularly.

If you never heard about property based testing, you might be interested by reading this quick introduction first.

Same article on dev.to at https://dev.to/dubzzz/your-own-property-based-testing-framework-part-1-generators-3afi

Concerning property based testing everything started at the end of 2017…

At that time I was trying to apply property based testing on User Interfaces as explained by this article from the author of RapidCheck or my article. So I took the leading JavaScript property based testing library and tried to add model based testing support to it… but failed.

So after weeks of trial and errors, I finally changed my mind and wanted to understand how things worked under the hood to get why it did not work. The result of this analysis is fast-check — a property based testing framework written in TypeScript for both JavaScript and TypeScript users.

Logo of fast-check

Throughout this serie of articles we will see how to build our own property based testing library from scratch. Our wonderful library will be called miniFc, it will expose all the features required for property based testing from generation of random values to shrinking capabilities.

But let’s start from the beginning…

In property based testing everything starts with generators. Generators take a random number generator and build anything out of it.

You can see generators as follow:

In the signature above mrng is a mutable random generator. It is a simple wrapper around pure-rand that provides a usable random instance. The class Random can be implemented as follow:

Let’s build our first generator: the one responsible to build random integers.

Our random integer Generator is simply returning the value forged by the passed random number generator.

We want to go further as generators should be able to generate not only integers, they are supposed to generate barely any kind of values. In fast-check, you can generate numbers, strings, arrays but also objects, functions, recursive structures and also infinite streams of any kind of stuff. In order to produce so many different kind of values without copying the same code again and again, they rely on taking root structures and deriving them into more complex ones as described below:

Let’s first consider boolean and character. In the diagram above they are constructed out of integer generator. In order to do so, we need to introduce an extra function called map. It will take an existing generator and a mapper function and create another generator out of it:

It can be implemented as follow:

Now that we have map we can implement some of our missing generators:

In order to build others, we first need to implement a generator for tuples and a generator for arrays:

Now we can build our last generators:

Given all the work above, you should be able to generate values ranging from simple booleans to complex dictionaries.

A playable example is available at https://runkit.com/dubzzz/part-1-generators

--

--