-
-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Combining two or more arbitraries into a new one by using generated values from the individual arbitraries is a crucial capability when design more complex properties. Jqwik 1 has two approaches: Combinators and Builders.
For jqwik 2 I suggest to keep the Combinators approach but replace Builders with a more generic approach that allows to "sample" values from any available arbitrary and use it in creating a new one.
Combinators
Combine two or more arbitraries by providing a function that takes a value per arbitrary and uses the taken values to create another arbitrary. Example:
Arbitrary<String> names = ...;
Arbitrary<Integer> ages = ...;
Arbitrary<Person> people = Combinators.combine(names, ages)
.as((name, age) -> new Person(name, age));
This is straightforward and seems to be intuitive to most developers.
Jqwik 1 defines combinator functions for up to 8 arbitraries.
Generic Sampling
Arbitrary<String> names = ...;
Arbitrary<Integer> ages = ...;
Arbitrary<Person> people = Sampler.use((Sampler sampler) -> {
int age = sampler.draw(ages);
String name = sampler.draw(names);
return new Person(name, age);
});
This approach has two advantages:
- It allows for any number of arbitraries to be used
- It allwos for any number and nesting of combination steps
Mind that this approach cannot be implemented in Jqwik 1 due to how Jqwik 1 implements shrinking and randomized generation.
Discussion
In principle the Generic Sampling approach makes the Combinators approach redundant, because it's more powerful.
I'd still keep it, since combinators seem to be more intuitive and provide better discoverability.