I need to write some unit tests in Catch2 where each test case should be executed for each possible permutation of two lists of types. I'd love something like
// Some types defined in my project
class A;
class B;
PERMUTATION_TEST_CASE ("Foo", (A, B), (float, double))
{
TestTypeX x;
TestTypeY y;
}
Where the test case would be executed 4 times with
TestTypeX = A, TestTypeY = float
TestTypeX = A, TestTypeY = double
TestTypeX = B, TestTypeY = float
TestTypeX = B, TestTypeY = double
Alternatively, something like this would also be possible
constexpr A a;
constexpr B b;
TEMPLATE_TEST_CASE ("Foo", float, double)
{
auto x = GENERATE (a, b); // does not work because a and b have different types
TestType y;
}
To my knowledge, there is no such thing in catch2. There is , in type-parametrised-test-cases, TEMPLATE_TEST_CASE
which solves the problem for a single list of types but not each permutation of two lists and there is TEMPLATE_PRODUCT_TEST_CASE
which solves the problem in case of the first type being a template which is then instantiated with each type of the second list – which is also not what I need here.
Is there any suitable catch2 mechanism for that which I'm overlooking at the moment? I'm using Catch2 version 3.1.0.
My real-world requirements are much larger sets of combinations than this 2x2 example, so manually specifying all permutations would not be my favourite choice.
You can create the Cartesian product of type list, and then:
using MyTypes = cross_product<type_list<A, B>, type_list<float, double>>::type;
// using MyTypes = type_list<std::pair<A, float>, std::pair<A, double>,
// std::pair<B, float>, std::pair<B, double>>;
TEMPLATE_LIST_TEST_CASE("some_name", "[xxx]", MyTypes)
{
using TestTypeX = typename TestType::first_type; // A or B
using TestTypeY = typename TestType::second_type; // float or double
// ...
}
In the same way, TEMPLATE_PRODUCT_TEST_CASE
might be (ab)used with wrapper type:
template <typename T>
struct A_with
{
using first_type = A;
using second_type = T;
};
template <typename T>
struct B_with
{
using first_type = B;
using second_type = T;
};
TEMPLATE_PRODUCT_TEST_CASE("some name", "[xxx]", (A_with, B_with), (float, double))
{
using TestTypeX = typename TestType::first_type; // A or B
using TestTypeY = typename TestType::second_type; // float or double
// ...
}