Google Test:如何用同一单元测试代码验证两种不同功能
在Google Test中复用测试代码测试不同功能的几种方法
针对你要复用测试逻辑、仅在核心调用处存在差异的需求,下面是几种实用的实现方式:
方法一:使用参数化测试(Google Test原生支持)
参数化测试是Google Test专门处理“同逻辑多场景”的特性,能把不同的测试目标(比如函数A和B)作为参数传入同一个测试模板,避免重复编写测试代码。
实现步骤:
- 定义参数化测试类,参数类型可以是函数指针、
std::function或自定义函数对象,用来封装差异逻辑; - 用
TEST_P编写通用测试逻辑,在差异处调用参数对应的逻辑; - 用
INSTANTIATE_TEST_SUITE_P生成不同参数的测试用例。
示例代码:
#include <gtest/gtest.h> #include <functional> // 假设这是你要测试的两个目标函数 void functionA(int arg) { /* 功能A的实现 */ } void functionB(int arg) { /* 功能B的实现 */ } // 定义参数化测试类,参数为封装差异逻辑的函数 class SomeClassTest : public testing::TestWithParam<std::function<void(int)>> {}; // 通用测试逻辑 TEST_P(SomeClassTest, SomeFunctionality) { // 初始化测试(通用代码) // ... for (unsigned i = 0; i < 128; i++) { // 迭代前准备(通用代码) int base_arg = i * 2; // 示例参数计算 // 调用参数对应的函数(唯一差异点) GetParam()(base_arg); // 迭代后收尾(通用代码) // ... } // 测试收尾(通用代码) // ... } // 实例化两个测试用例,分别传入functionA和functionB INSTANTIATE_TEST_SUITE_P( DifferentFunctions, SomeClassTest, testing::Values( std::function<void(int)>(functionA), std::function<void(int)>(functionB) ) );
如果你的参数计算逻辑更复杂,可以用lambda封装完整的差异流程:
INSTANTIATE_TEST_SUITE_P( DifferentFunctions, SomeClassTest, testing::Values( [](int base) { // 针对A的参数计算逻辑 int processed_arg = base + 5; functionA(processed_arg); }, [](int base) { // 针对B的参数计算逻辑 int processed_arg = base * 3; functionB(processed_arg); } ) );
方法二:提取通用测试逻辑到辅助函数
如果觉得参数化测试过于繁琐,也可以把通用测试代码提取成普通函数,再在两个独立的TEST用例中调用这个函数,传入不同的回调处理差异部分。
示例代码:
#include <gtest/gtest.h> #include <functional> void functionA(int arg) { /* 功能A的实现 */ } void functionB(int arg) { /* 功能B的实现 */ } // 通用测试逻辑,接收回调处理差异 void RunCommonTest(const std::function<void(int)>& func) { // 初始化测试(通用代码) // ... for (unsigned i = 0; i < 128; i++) { // 迭代前准备(通用代码) int base_arg = i; // 调用传入的回调(差异点) func(base_arg); // 迭代后收尾(通用代码) // ... } // 测试收尾(通用代码) // ... } // 测试functionA的用例 TEST(SomeClass, TestFunctionA) { RunCommonTest([](int base) { // 针对A的参数计算 int processed_arg = base * 2; functionA(processed_arg); }); } // 测试functionB的用例 TEST(SomeClass, TestFunctionB) { RunCommonTest([](int base) { // 针对B的参数计算 int processed_arg = base + 10; functionB(processed_arg); }); }
方法三:测试夹具+子类(适合复杂差异场景)
如果除了函数调用,还有初始化/清理环节的细微差异,可以基于测试夹具创建子类,在子类中重写差异方法,再编写通用测试逻辑。
示例代码:
#include <gtest/gtest.h> void functionA(int arg) { /* 功能A的实现 */ } void functionB(int arg) { /* 功能B的实现 */ } // 基础测试夹具,定义通用逻辑和纯虚方法作为差异点 class SomeClassFixture : public testing::Test { protected: // 纯虚方法,由子类实现差异逻辑 virtual void TargetFunction(int arg) = 0; // 通用测试逻辑 void RunCommonLogic() { // 初始化测试(通用代码) // ... for (unsigned i = 0; i < 128; i++) { // 迭代前准备(通用代码) int base_arg = i; // 调用子类实现的方法 TargetFunction(base_arg); // 迭代后收尾(通用代码) // ... } // 测试收尾(通用代码) // ... } }; // 针对functionA的夹具子类 class TestFunctionAFixture : public SomeClassFixture { protected: void TargetFunction(int arg) override { // A的参数计算+调用 int processed_arg = arg * 2; functionA(processed_arg); } }; // 针对functionB的夹具子类 class TestFunctionBFixture : public SomeClassFixture { protected: void TargetFunction(int arg) override { // B的参数计算+调用 int processed_arg = arg + 5; functionB(processed_arg); } }; // 测试用例 TEST_F(TestFunctionAFixture, SomeFunctionality) { RunCommonLogic(); } TEST_F(TestFunctionBFixture, SomeFunctionality) { RunCommonLogic(); }
内容的提问来源于stack exchange,提问作者no one special
相关产品推荐
相关产品推荐

