如何在Catch2 3.1.0中实现两个类型列表的全排列测试?
如何在Catch2 3.1.0中实现多类型列表的全排列组合测试用例?
需求场景
需要编写单元测试,针对两个独立类型列表的所有笛卡尔积组合执行测试,期望实现类似如下语法的效果:
// 项目中定义的类型 class A; class B; PERMUTATION_TEST_CASE("Foo", (A, B), (float, double)) { TestTypeX x; TestTypeY y; }
该测试需覆盖4种类型组合:
- TestTypeX = A, TestTypeY = float
- TestTypeX = A, TestTypeY = double
- TestTypeX = B, TestTypeY = float
- TestTypeX = B, TestTypeY = double
之前尝试用GENERATE结合TEMPLATE_TEST_CASE的写法失败,因为GENERATE要求所有生成值的类型一致,无法同时传入不同类型的对象:
constexpr A a; constexpr B b; TEMPLATE_TEST_CASE("Foo", float, double) { auto x = GENERATE(a, b); // 类型不匹配,无法运行 TestType y; }
可行解决方案
Catch2 3.1.0中没有直接的PERMUTATION_TEST_CASE,但可以通过**TEMPLATE_PRODUCT_TEST_CASE配合类型配对模板**实现需求,这是最简洁的编译期解决方案:
步骤1:定义类型配对模板
首先创建一个简单的模板结构体,用于绑定两个类型:
template<typename X, typename Y> struct TypePair { using First = X; using Second = Y; };
步骤2:用TEMPLATE_PRODUCT_TEST_CASE生成所有组合
利用TEMPLATE_PRODUCT_TEST_CASE将两个类型列表与TypePair模板结合,生成所有笛卡尔积组合:
// 项目中定义的类型 class A; class B; template<typename X, typename Y> struct TypePair { using First = X; using Second = Y; }; TEMPLATE_PRODUCT_TEST_CASE("Foo", "", TypePair, (A, B), (float, double)) { // 从TypePair中提取两个测试类型 using TestTypeX = typename TestType::First; using TestTypeY = typename TestType::Second; // 实例化测试对象并执行测试逻辑 TestTypeX x; TestTypeY y; // 这里编写你的测试断言 REQUIRE(true); // 示例断言 }
方案说明
TEMPLATE_PRODUCT_TEST_CASE会遍历所有传入的类型列表组合,将TypePair模板实例化为TypePair<A,float>、TypePair<A,double>等所有可能的组合。- 通过
TestType::First和TestType::Second可以分别提取两个类型,完全符合你期望的TestTypeX和TestTypeY的用法。 - 该方案是编译期生成测试用例,性能和扩展性都很好,即使类型列表很长(比如10x10的组合)也能自动生成所有测试。
替代方案:嵌套TEMPLATE_TEST_CASE
如果不想额外定义TypePair,也可以用两层嵌套的TEMPLATE_TEST_CASE实现,缺点是测试名称会嵌套:
class A; class B; TEMPLATE_TEST_CASE("Foo - TypeX", "", A, B) { TEMPLATE_TEST_CASE("TypeY combinations", "", float, double) { // 外层TestType对应A/B,内层TestTypeInner对应float/double TestType x; TestTypeInner y; // 测试逻辑 REQUIRE(true); } }
内容的提问来源于stack exchange,提问作者PluginPenguin
相关产品推荐
相关产品推荐

