如何用Catch2高效测试里氏替换原则?消除测试代码冗余
用Catch2批量验证C++派生类的基类规范(避免重复代码)
在Catch2框架中,有两种实用方式可以避免测试派生类时的代码重复:
方法一:模板函数封装通用测试逻辑
把验证基类规范的核心逻辑抽成模板函数,针对每个派生类直接调用即可,代码清晰且易于维护:
// 封装通用测试逻辑的模板函数 template<typename T> void verify_base_spec() { T instance; auto result = instance.do_something(); REQUIRE(result != ""); } TEST_CASE("验证派生类符合基类规范") { SECTION("测试派生类A") { verify_base_spec<A>(); } SECTION("测试派生类B") { verify_base_spec<B>(); } // 可选:测试基类本身 SECTION("测试基类") { verify_base_spec<Base>(); } }
方法二:用GENERATE宏实现参数化测试
如果需要测试的派生类数量较多,使用Catch2的GENERATE宏可以批量生成测试用例,进一步简化代码:
方式1:基于工厂函数的参数化
#include <memory> // 工厂函数:创建对应类型的实例 template<typename T> std::unique_ptr<Base> create_instance() { return std::make_unique<T>(); } TEST_CASE("参数化验证派生类规范") { // 生成多个类型的工厂函数 auto factory = GENERATE(create_instance<A>, create_instance<B>, create_instance<Base>); auto obj = factory(); auto result = obj->do_something(); REQUIRE(result != ""); }
方式2:基于类型标签的参数化
这种方式不需要基类指针,直接操作具体类型:
// 辅助类型标签 template<typename T> struct TypeTag { using type = T; }; TEST_CASE("参数化测试派生类") { // 生成不同类型的标签 auto type_tag = GENERATE(TypeTag<A>{}, TypeTag<B>{}, TypeTag<Base>{}); // 用泛型lambda处理不同类型 auto run_test = [](auto tag) { using T = typename decltype(tag)::type; T instance; REQUIRE(instance.do_something() != ""); }; run_test(type_tag); }
两种方法对比
- 模板函数方式:每个派生类对应独立的测试Section,测试失败时能快速定位到具体类,适合派生类数量不多的场景。
- 参数化方式:代码更紧凑,适合大量派生类的批量测试,但测试报告中会将所有实例显示为同一个测试用例的不同参数。
内容的提问来源于stack exchange,提问作者Brandon
相关产品推荐
相关产品推荐

