// 300-Gen-OwnGenerator.cpp // Shows how to define a custom generator. // Specifically we will implement a random number generator for integers // It will have infinite capacity and settable lower/upper bound #include #include #include #include namespace { // This class shows how to implement a simple generator for Catch tests class RandomIntGenerator : public Catch::Generators::IGenerator { std::minstd_rand m_rand; std::uniform_int_distribution<> m_dist; int current_number; public: RandomIntGenerator(int low, int high): m_rand(std::random_device{}()), m_dist(low, high) { static_cast(next()); } int const& get() const override; bool next() override { current_number = m_dist(m_rand); return true; } }; // Avoids -Wweak-vtables int const& RandomIntGenerator::get() const { return current_number; } // This helper function provides a nicer UX when instantiating the generator // Notice that it returns an instance of GeneratorWrapper, which // is a value-wrapper around std::unique_ptr>. Catch::Generators::GeneratorWrapper random(int low, int high) { return Catch::Generators::GeneratorWrapper( new RandomIntGenerator(low, high) // Another possibility: // Catch::Detail::make_unique(low, high) ); } } // end anonymous namespaces // The two sections in this test case are equivalent, but the first one // is much more readable/nicer to use TEST_CASE("Generating random ints", "[example][generator]") { SECTION("Nice UX") { auto i = GENERATE(take(100, random(-100, 100))); REQUIRE(i >= -100); REQUIRE(i <= 100); } SECTION("Creating the random generator directly") { auto i = GENERATE(take(100, GeneratorWrapper(Catch::Detail::make_unique(-100, 100)))); REQUIRE(i >= -100); REQUIRE(i <= 100); } } // Compiling and running this file will result in 400 successful assertions