mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 12:17:11 +01:00 
			
		
		
		
	Update documentation and examples for generators
This commit is contained in:
		
							
								
								
									
										59
									
								
								examples/300-Gen-OwnGenerator.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								examples/300-Gen-OwnGenerator.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| // 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 <catch2/catch.hpp> | ||||
|  | ||||
| #include <random> | ||||
|  | ||||
| // This class shows how to implement a simple generator for Catch tests | ||||
| class RandomIntGenerator : public Catch::Generators::IGenerator<int> { | ||||
|     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<void>(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<int>, which | ||||
| // is a value-wrapper around std::unique_ptr<IGenerator<int>>. | ||||
| Catch::Generators::GeneratorWrapper<int> random(int low, int high) { | ||||
|     return Catch::Generators::GeneratorWrapper<int>(std::unique_ptr<Catch::Generators::IGenerator<int>>(new RandomIntGenerator(low, high))); | ||||
| } | ||||
|  | ||||
| // 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<int>(std::unique_ptr<IGenerator<int>>(new RandomIntGenerator(-100, 100))))); | ||||
|         REQUIRE(i >= -100); | ||||
|         REQUIRE(i <= 100); | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Compiling and running this file will result in 400 successful assertions | ||||
							
								
								
									
										72
									
								
								examples/310-Gen-VariablesInGenerators.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								examples/310-Gen-VariablesInGenerators.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| // 310-Gen-VariablesInGenerator.cpp | ||||
| // Shows how to use variables when creating generators. | ||||
|  | ||||
| // Note that using variables inside generators is dangerous and should | ||||
| // be done only if you know what you are doing, because the generators | ||||
| // _WILL_ outlive the variables -- thus they should be either captured | ||||
| // by value directly, or copied by the generators during construction. | ||||
|  | ||||
| #include <catch2/catch.hpp> | ||||
|  | ||||
| #include <random> | ||||
|  | ||||
| // Lets start by implementing a parametrizable double generator | ||||
| class RandomDoubleGenerator : public Catch::Generators::IGenerator<double> { | ||||
|     std::minstd_rand m_rand; | ||||
|     std::uniform_real_distribution<> m_dist; | ||||
|     double current_number; | ||||
| public: | ||||
|  | ||||
|     RandomDoubleGenerator(double low, double high): | ||||
|         m_rand(std::random_device{}()), | ||||
|         m_dist(low, high) | ||||
|     { | ||||
|         static_cast<void>(next()); | ||||
|     } | ||||
|  | ||||
|     double const& get() const override; | ||||
|     bool next() override { | ||||
|         current_number = m_dist(m_rand); | ||||
|         return true; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| // Avoids -Wweak-vtables | ||||
| double const& RandomDoubleGenerator::get() const { | ||||
|     return current_number; | ||||
| } | ||||
|  | ||||
|  | ||||
| // Also provide a nice shortcut for creating the generator | ||||
| Catch::Generators::GeneratorWrapper<double> random(double low, double high) { | ||||
|     return Catch::Generators::GeneratorWrapper<double>(std::unique_ptr<Catch::Generators::IGenerator<double>>(new RandomDoubleGenerator(low, high))); | ||||
| } | ||||
|  | ||||
|  | ||||
| TEST_CASE("Generate random doubles across different ranges", | ||||
|           "[generator][example][advanced]") { | ||||
|     // Workaround for old libstdc++ | ||||
|     using record = std::tuple<double, double>; | ||||
|     // Set up 3 ranges to generate numbers from | ||||
|     auto r = GENERATE(table<double, double>({ | ||||
|         record{3, 4}, | ||||
|         record{-4, -3}, | ||||
|         record{10, 1000} | ||||
|     })); | ||||
|  | ||||
|     // This will not compile (intentionally), because it accesses a variable | ||||
|     // auto number = GENERATE(take(50, random(r.first, r.second))); | ||||
|      | ||||
|     // We have to manually register the generators instead | ||||
|     // Notice that we are using value capture in the lambda, to avoid lifetime issues | ||||
|     auto number = Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, | ||||
|         [=]{ | ||||
|             using namespace Catch::Generators; | ||||
|             return makeGenerators(take(50, random(std::get<0>(r), std::get<1>(r)))); | ||||
|         } | ||||
|     ); | ||||
|     REQUIRE(std::abs(number) > 0); | ||||
| } | ||||
|  | ||||
| // Compiling and running this file will result in 150 successful assertions | ||||
|  | ||||
| @@ -44,6 +44,8 @@ set( SOURCES_IDIOMATIC_TESTS | ||||
|     110-Fix-ClassFixture.cpp | ||||
|     120-Bdd-ScenarioGivenWhenThen.cpp | ||||
|     210-Evt-EventListeners.cpp | ||||
|     300-Gen-OwnGenerator.cpp | ||||
|     310-Gen-VariablesInGenerators.cpp | ||||
| ) | ||||
|  | ||||
| # main-s for reporter-specific test sources: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Martin Hořeňovský
					Martin Hořeňovský