Wire Sysio Wire Sysion 1.0.0
|
Data generators (also known as data driven/parametrized test cases) let you reuse the same set of assertions across different input values. In Catch2, this means that they respect the ordering and nesting of the TEST_CASE
and SECTION
macros, and their nested sections are run once per each value in a generator.
This is best explained with an example:
The assertion in this test case will be run 9 times, because there are 3 possible values for i
(1, 2, and 3) and there are 3 possible values for j
(-3, -2, and -1).
There are 2 parts to generators in Catch2, the GENERATE
macro together with the already provided generators, and the IGenerator<T>
interface that allows users to implement their own generators.
Catch2's provided generator functionality consists of three parts,
GENERATE
macro, that serves to integrate generator expression with a test case,ValueGenerator<T>
– contains only single elementValuesGenerator<T>
– contains multiple elementsFilterGenerator<T, Predicate>
– filters out elements from a generator for which the predicate returns "false"TakeGenerator<T>
– takes first n
elements from a generatorRepeatGenerator<T>
– repeats output from a generator n
timesMapGenerator<T, U, Func>
– returns the result of applying Func
on elements from a different generatorChunkGenerator<T>
– returns chunks (inside std::vector
) of n elements from a generatorRandomIntegerGenerator<Integral>
– generates random Integrals from rangeRandomFloatGenerator<Float>
– generates random Floats from rangeRangeGenerator<T>
– generates all values inside a specific rangeThe generators also have associated helper functions that infer their type, making their usage much nicer. These are
value(T&&)
for ValueGenerator<T>
values(std::initializer_list<T>)
for ValuesGenerator<T>
filter(predicate, GeneratorWrapper<T>&&)
for FilterGenerator<T, Predicate>
take(count, GeneratorWrapper<T>&&)
for TakeGenerator<T>
repeat(repeats, GeneratorWrapper<T>&&)
for RepeatGenerator<T>
map(func, GeneratorWrapper<T>&&)
for MapGenerator<T, U, Func>
(map U
to T
, deduced from Func
)map<T>(func, GeneratorWrapper<U>&&)
for MapGenerator<T, U, Func>
(map U
to T
)chunk(chunk-size, GeneratorWrapper<T>&&)
for ChunkGenerator<T>
random(IntegerOrFloat a, IntegerOrFloat b)
for RandomIntegerGenerator
or RandomFloatGenerator
range(start, end)
for RangeGenerator<T>
with a step size of 1
range(start, end, step)
for RangeGenerator<T>
with a custom step sizeAnd can be used as shown in the example below to create a generator that returns 100 odd random number:
Apart from registering generators with Catch2, the GENERATE
macro has one more purpose, and that is to provide simple way of generating trivial generators, as seen in the first example on this page, where we used it as auto i = GENERATE(1, 2, 3);
. This usage converted each of the three literals into a single ValueGenerator<int>
and then placed them all in a special generator that concatenates other generators. It can also be used with other generators as arguments, such as auto i = GENERATE(0, 2, take(100, random(300, 3000)));
. This is useful e.g. if you know that specific inputs are problematic and want to test them separately/first.
For safety reasons, you cannot use variables inside the GENERATE
macro. This is done because the generator expression will outlive the outside scope and thus capturing references is dangerous. If you need to use variables inside the generator expression, make sure you thought through the lifetime implications and use GENERATE_COPY
or GENERATE_REF
.
You can also override the inferred type by using as<type>
as the first argument to the macro. This can be useful when dealing with string literals, if you want them to come out as std::string
:
You can also implement your own generators, by deriving from the IGenerator<T>
interface:
However, to be able to use your custom generator inside GENERATE
, it will need to be wrapped inside a GeneratorWrapper<T>
. GeneratorWrapper<T>
is a value wrapper around a std::unique_ptr<IGenerator<T>>
.
For full example of implementing your own generator, look into Catch2's examples, specifically Generators: Create your own generator.