如何使用Googletest为枚举值编写模板化单元测试?
问题描述
Googletest针对标准类型的模板化测试文档较为完善,但我想要编写以enum具体值作为模板参数的测试,尝试的代码编译失败,不确定是否可行。
我编写的代码如下:
enum Dinosaur { Trex = 0, Stegosaur = 1, Triceratops = 2 }; using MyDinosaurs = ::testing::Types< Dinosaur::Trex, Dinosaur::Stegosaur, Dinosaur::Triceratops>; // 编译失败:Dinosaur::Trex等并非实际类型 template <Dinosaur Dinosaur_T> class DinosaurTest : public ::testing::Test { private: DinosaurFactory<Dinosaur_T> m_dinosaurFactory; }; TYPED_TEST_SUITE(DinosaurTest, MyDinosaurs); TYPED_TEST_P(DinosaurTest, DinosaurEnumTest) { ASSERT_NE(nullptr, m_dinosaurFactory.Create()); } REGISTER_TYPED_TEST_SUITE_P(DinosaurTest, DinosaurEnumTest); INSTANTIATE_TYPED_TEST_SUITE_P(MyDinosaurTestSuite, DinosaurTest, MyDinosaurs); // 编译失败:'MyDinosaurs'不是有效类型列表
请问如何实现这类针对枚举值的模板化测试?
解决方案
Googletest的TYPED_TEST系列宏仅支持类型作为模板参数,不支持非类型模板参数(比如枚举值)。要实现枚举值的参数化测试,有两种实用方案:
方案1:用包装类封装枚举值
将每个枚举值包装为独立的类型,让Googletest可以识别并作为模板参数使用:
enum Dinosaur { Trex = 0, Stegosaur = 1, Triceratops = 2 }; // 为每个枚举值定义对应的包装类 struct TrexWrapper { static constexpr Dinosaur value = Dinosaur::Trex; }; struct StegosaurWrapper { static constexpr Dinosaur value = Dinosaur::Stegosaur; }; struct TriceratopsWrapper { static constexpr Dinosaur value = Dinosaur::Triceratops; }; // 构建Googletest可识别的类型列表 using MyDinosaurs = ::testing::Types<TrexWrapper, StegosaurWrapper, TriceratopsWrapper>; // 测试类以包装类为模板参数 template <typename Wrapper> class DinosaurTest : public ::testing::Test { private: // 从包装类中提取枚举值 static constexpr Dinosaur Dinosaur_T = Wrapper::value; DinosaurFactory<Dinosaur_T> m_dinosaurFactory; }; TYPED_TEST_SUITE(DinosaurTest, MyDinosaurs); TYPED_TEST_P(DinosaurTest, DinosaurEnumTest) { ASSERT_NE(nullptr, this->m_dinosaurFactory.Create()); } REGISTER_TYPED_TEST_SUITE_P(DinosaurTest, DinosaurEnumTest); INSTANTIATE_TYPED_TEST_SUITE_P(MyDinosaurTestSuite, DinosaurTest, MyDinosaurs);
方案2:使用TEST_P参数化测试(非模板测试类)
如果不需要模板测试类,直接用Googletest的参数化测试框架更简洁:
enum Dinosaur { Trex = 0, Stegosaur = 1, Triceratops = 2 }; // 定义参数化测试类,接收枚举值作为测试参数 class DinosaurTest : public ::testing::TestWithParam<Dinosaur> { private: // C++17及以上支持直接用GetParam()作为模板参数 DinosaurFactory<GetParam()> m_dinosaurFactory; }; // 定义测试用例 TEST_P(DinosaurTest, DinosaurEnumTest) { ASSERT_NE(nullptr, m_dinosaurFactory.Create()); } // 实例化测试,传入所有需要测试的枚举值 INSTANTIATE_TEST_SUITE_P( MyDinosaurTestSuite, DinosaurTest, ::testing::Values(Dinosaur::Trex, Dinosaur::Stegosaur, Dinosaur::Triceratops) );
注意事项
- 方案2中,
DinosaurFactory<GetParam()>依赖C++17的模板参数推导特性,如果编译器版本较低,可以调整DinosaurFactory的设计(比如改为运行时传入枚举值)来兼容。 - 如果测试类需要基于模板做复杂的初始化或类型适配,优先选择方案1。
内容的提问来源于stack exchange,提问作者Yellow
相关产品推荐
相关产品推荐

