Building Custom Generator from Scratch¶
New to property-based testing? Start with the Walkthrough for a step-by-step guide. Before building a custom generator from scratch, consider combining existing generators with combinators—
.filter(),.map<U>(),.flatMap<U>(),.pairWith<U>(), or gen::construct often suffice. Build from scratch only when you need generation logic that cannot be expressed by composing these.
When to Build from Scratch¶
Custom generators are useful when:
- You need values from a domain not covered by built-in generators or Arbitraries
- Combinators (filter, map, flatMap, construct) cannot express your constraints or transformations
- You need custom shrinking behavior (see Shrinking)
- You want to define a default generator for a type used across many tests (see Arbitrary)
Generator<T> and Arbitrary<T>¶
Generator<T> and Arbitrary<T> are the standard generator types in cppproptest. Both share the same chainable utility methods (.filter(), .map<U>(), .flatMap<U>(), etc.). Generator<T> is commonly the result of combinators; Arbitrary<T> is the default generator for a type. They are fully chainable—you can use any generator with forAll and chain methods as needed.
Building a Custom Generator¶
A generator in cppproptest is simply a callable with signature (Random&) -> Shrinkable<T>. Simplest way to make a shrinkable is to use make_shrinkable<T>(value) to wrap your value. This makes a shrinkable with no further shrinks. See Shrinking for details on Shrinkable.
You can wrap your callable with Generator<T> to decorate it as a standard generator with same chainable utility methods as built-in generators and Arbitraries:
auto myIntGen = Generator<int>([](Random& rand) {
int smallInt = rand.getRandomInt8();
return make_shrinkable<int>(smallInt);
});
// Chain with .filter(), .map(), etc. like any other standard generators
auto evenGen = myIntGen.filter([](const int& value) {
return value % 2 == 0;
});
Related Topics¶
- Combinators -
.filter(),.map(),.flatMap(), and other utility methods for transforming generators - Generators - Built-in generators for primitives and containers
- Arbitrary - Defining default generators for types used in
forAllwithout explicit generator arguments - Shrinking - How
Shrinkableandmake_shrinkableenable automated simplification of failing inputs - Property API - Using custom generators with
forAllandproperty() - Walkthrough - Step-by-step guide for creating property tests