#readwise
# The Test Data Generator Functor

## Metadata
- Author: [[Mark Seemann]]
- Full Title: The Test Data Generator Functor
- URL: https://blog.ploeh.dk/2017/09/18/the-test-data-generator-functor/
## Highlights
- Closely related to [[From Test Data Builders to the Identity Functor|Test Data Builders]] is the concept of a generator of random test data. You could call it a Test Data Generator instead. Such a generator can be modelled as a functor. ... At its core, **the idea behind a Test Data Generator is to create random test data. Still, you'll like to be able control various parts of the process, because you'd often need to pin parts of the generated data to deterministic values, while allowing other parts to vary randomly.**
- In C#, you can write a generic Generator like this:
```csharp
public class Generator<T>
{
private readonly Func<Random, T> generate;
public Generator(Func<Random, T> generate)
{
if (generate == null)
throw new ArgumentNullException(nameof(generate));
this.generate = generate;
}
public Generator<T1> Select<T1>(Func<T, T1> f)
{
if (f == null)
throw new ArgumentNullException(nameof(f));
Func<Random, T1> newGenerator = r => f(this.generate(r));
return new Generator<T1>(newGenerator);
}
public T Generate(Random random)
{
if (random == null)
throw new ArgumentNullException(nameof(random));
return this.generate(random);
}
}
```
(For the FP enthusiasts, **this is simply the *Reader functor* in disguise**.)
- The above `Generator<T>` is only a crude example of a Test Data Generator. In order to demonstrate how such a generator is a functor, I left out several useful features. Still, this should have given you a sense for how the `Generator<T>` class itself, as well as such general-purpose building blocks as `Many` and `AlphaNumericString`, could be packaged in a reusable library.
The examples above show how to use a generator to create a single random object. You could, however, easily generate many (say, 100) random objects, and run unit tests for each object created. This is the idea behind property-based testing.
There's more to property-based testing than generation of random values, but the implementations I've seen are all based on Test Data Generators as functors (and monads). ([View Highlight](https://read.readwise.io/read/01gwkee650yg1f0rx09tyvrhc5))
- **[FsCheck](https://fscheck.github.io/FsCheck) is an open source F# library for property-based testing. It defines a `Gen` functor (and monad)** that you can use to generate `Address` values, just like the above examples ([View Highlight](https://read.readwise.io/read/01gwkef9wvh6a61c5vbd730yyg))
- [Hedgehog](https://github.com/hedgehogqa/fsharp-hedgehog) is another open source F# library for property-based testing. ([View Highlight](https://read.readwise.io/read/01gwkegame15qxfgn8t5j4bffj))
- This is *literally* the same syntax as FsCheck! This isn't because Hedgehog is copying FsCheck, but because both are based on the same underlying abstraction: functor (and monad). There are other parts of the API where Hedgehog differs from FsCheck, but their generators are similar.
**This is one of the most important advantages of using well-known abstractions like functors. Once you understand such an abstraction, it's easy to learn a new library.** With professional experience with FsCheck, it only took me a few minutes to figure out how to use Hedgehog. ([View Highlight](https://read.readwise.io/read/01gwkeh3x0rnaq1s5m7517a2jk))
- Functors are well-defined objects from category theory. It may seem abstract, and far removed from 'real' programming, but it's extraordinarily useful. Many category theory abstractions can be applied to a host of different situations. Once you've learned what a functor is, you'll find it easy to learn to use new libraries that build on that abstraction. ([View Highlight](https://read.readwise.io/read/01gwkehwk364k51brjk46q9p5s))