1<a id="top"></a> 2# Data Generators 3 4Data generators (also known as _data driven/parametrized test cases_) 5let you reuse the same set of assertions across different input values. 6In Catch2, this means that they respect the ordering and nesting 7of the `TEST_CASE` and `SECTION` macros, and their nested sections 8are run once per each value in a generator. 9 10This is best explained with an example: 11```cpp 12TEST_CASE("Generators") { 13 auto i = GENERATE(1, 2, 3); 14 SECTION("one") { 15 auto j = GENERATE( -3, -2, -1 ); 16 REQUIRE(j < i); 17 } 18} 19``` 20 21The assertion in this test case will be run 9 times, because there 22are 3 possible values for `i` (1, 2, and 3) and there are 3 possible 23values for `j` (-3, -2, and -1). 24 25 26There are 2 parts to generators in Catch2, the `GENERATE` macro together 27with the already provided generators, and the `IGenerator<T>` interface 28that allows users to implement their own generators. 29 30## Provided generators 31 32Catch2's provided generator functionality consists of three parts, 33 34* `GENERATE` macro, that serves to integrate generator expression with 35a test case, 36* 2 fundamental generators 37 * `ValueGenerator<T>` -- contains only single element 38 * `ValuesGenerator<T>` -- contains multiple elements 39* 5 generic generators that modify other generators 40 * `FilterGenerator<T, Predicate>` -- filters out elements from a generator 41 for which the predicate returns "false" 42 * `TakeGenerator<T>` -- takes first `n` elements from a generator 43 * `RepeatGenerator<T>` -- repeats output from a generator `n` times 44 * `MapGenerator<T, U, Func>` -- returns the result of applying `Func` 45 on elements from a different generator 46 * `ChunkGenerator<T>` -- returns chunks (inside `std::vector`) of n elements from a generator 47* 3 specific purpose generators 48 * `RandomIntegerGenerator<Integral>` -- generates random Integrals from range 49 * `RandomFloatGenerator<Float>` -- generates random Floats from range 50 * `RangeGenerator<T>` -- generates all values inside a specific range 51 52The generators also have associated helper functions that infer their 53type, making their usage much nicer. These are 54 55* `value(T&&)` for `ValueGenerator<T>` 56* `values(std::initializer_list<T>)` for `ValuesGenerator<T>` 57* `filter(predicate, GeneratorWrapper<T>&&)` for `FilterGenerator<T, Predicate>` 58* `take(count, GeneratorWrapper<T>&&)` for `TakeGenerator<T>` 59* `repeat(repeats, GeneratorWrapper<T>&&)` for `RepeatGenerator<T>` 60* `map(func, GeneratorWrapper<T>&&)` for `MapGenerator<T, T, Func>` (map `T` to `T`) 61* `map<T>(func, GeneratorWrapper<U>&&)` for `MapGenerator<T, U, Func>` (map `U` to `T`) 62* `chunk(chunk-size, GeneratorWrapper<T>&&)` for `ChunkGenerator<T>` 63* `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator` 64* `range(start, end)` for `RangeGenerator<T>` with a step size of `1` 65* `range(start, end, step)` for `RangeGenerator<T>` with a custom step size 66 67 68And can be used as shown in the example below to create a generator 69that returns 100 odd random number: 70 71```cpp 72TEST_CASE("Generating random ints", "[example][generator]") { 73 SECTION("Deducing functions") { 74 auto i = GENERATE(take(100, filter([](int i) { return i % 2 == 1; }, random(-100, 100)))); 75 REQUIRE(i > -100); 76 REQUIRE(i < 100); 77 REQUIRE(i % 2 == 1); 78 } 79} 80``` 81 82 83Apart from registering generators with Catch2, the `GENERATE` macro has 84one more purpose, and that is to provide simple way of generating trivial 85generators, as seen in the first example on this page, where we used it 86as `auto i = GENERATE(1, 2, 3);`. This usage converted each of the three 87literals into a single `ValueGenerator<int>` and then placed them all in 88a special generator that concatenates other generators. It can also be 89used with other generators as arguments, such as `auto i = GENERATE(0, 2, 90take(100, random(300, 3000)));`. This is useful e.g. if you know that 91specific inputs are problematic and want to test them separately/first. 92 93**For safety reasons, you cannot use variables inside the `GENERATE` macro.** 94 95You can also override the inferred type by using `as<type>` as the first 96argument to the macro. This can be useful when dealing with string literals, 97if you want them to come out as `std::string`: 98 99```cpp 100TEST_CASE("type conversion", "[generators]") { 101 auto str = GENERATE(as<std::string>{}, "a", "bb", "ccc");` 102 REQUIRE(str.size() > 0); 103} 104``` 105 106## Generator interface 107 108You can also implement your own generators, by deriving from the 109`IGenerator<T>` interface: 110 111```cpp 112template<typename T> 113struct IGenerator : GeneratorUntypedBase { 114 // via GeneratorUntypedBase: 115 // Attempts to move the generator to the next element. 116 // Returns true if successful (and thus has another element that can be read) 117 virtual bool next() = 0; 118 119 // Precondition: 120 // The generator is either freshly constructed or the last call to next() returned true 121 virtual T const& get() const = 0; 122}; 123``` 124 125However, to be able to use your custom generator inside `GENERATE`, it 126will need to be wrapped inside a `GeneratorWrapper<T>`. 127`GeneratorWrapper<T>` is a value wrapper around a 128`std::unique_ptr<IGenerator<T>>`. 129 130For full example of implementing your own generator, look into Catch2's 131examples, specifically 132[Generators: Create your own generator](../examples/300-Gen-OwnGenerator.cpp). 133 134