做网站空,深圳创业补贴2024,360网站提交收录入口,wordpress 标题关键词TDD#xff0c;测试驱动开发#xff0c;英文全称Test-Driven Development#xff0c;简称TDD#xff0c;是一种不同于传统软件开发流程的新型的开发方法。它要求在编写某个功能的代码之前先编写测试代码#xff0c;然后只编写使测试通过的功能代码#xff0c;通过测试来推…TDD测试驱动开发英文全称Test-Driven Development简称TDD是一种不同于传统软件开发流程的新型的开发方法。它要求在编写某个功能的代码之前先编写测试代码然后只编写使测试通过的功能代码通过测试来推动整个开发的进行。这有助于编写简洁可用和高质量的代码并加速开发过程。
简言之TDD是通过设计 Test 来完成软件设计的一种高效可行的软件开发模式。
为何更丰富地达成测试的目的googletes是绕不过去的本文备忘主要关注 googletest 主体的分析过程和结论即googleTest框架中是如何通过相关的测试宏的实现测试的目的。
TEST TEST_F TEST_P 等等 1googleTest 环境与简单示例 1.1 下载 googletest 并编译
下载
$ git clone https://github.com/google/googletest.git
$ git checkout release-1.10.0
编译
$ mkdir build
$ cd build/
$ export CXXFLAGS-Wno-errormaybe-uninitialized
$ cmake ..
$ make -j
$ ls lib/ 默认为 release若debug版本则须
$ cmake .. -DCMAKE_BUILD_TYPEDebug 成果 1.2 示例1 验证函数 add
源码
#include iostream
#include gtest/gtest.hint add_int_int(int a, int b){return ab;
}TEST(SumFuncTest, twoNumbers){EXPECT_EQ(add_int_int(3,4),7);EXPECT_EQ(27, add_int_int(9, 18));
}GTEST_API_ int main(int argc, char** argv) {printf(Running main() from %s\n, __FILE__);testing::InitGoogleTest(argc, argv);return RUN_ALL_TESTS();
}
运行 1.3 示例 2
#include gtest/gtest.hint Foo(int a, int b)
{if (a 0 || b 0){throw dont do that;}int c a % b;if (c 0)return b;return Foo(b, c);
}TEST(FooTest, HandleNoneZeroInput)
{EXPECT_EQ(2, Foo(4, 10));EXPECT_EQ(6, Foo(30, 18));
}g foo.cpp -I ../../googletest/googletest/include -L ../../googletest/build_dbg/lib -lgtest -lgtest_main
编译运行 1.4 示例3
源码
#include iostream
#include gtest/gtest.h// add_util.ccfloat add_from_left(float a, float b, float c, float d, float e)
{float sum 0.0;sum c;sum a;sum b;//sum c;sum d;sum e;
/*sum a;sum b;sum c;sum d;sum e;
*/printf(add_from_left: sum %f\n, sum);return sum;
}float add_from_right(float a, float b, float c, float d, float e)
{float sum 0.0;sum e;sum d;sum c;sum b;sum a;printf(add_from_right: sum %f\n, sum);return sum;
}int sum(int a, int b){return ab;
}TEST(AddFuncTest, floatVSfloat) {printf(AddFuncTest: float sum %f\n, 1.238f 3.7f 0.000353265f 7898.3f 12.23209f);printf(AddFuncTest: double sum %f\n, 12.23209 7898.3 0.000353265 3.7 1.238);EXPECT_EQ(1.238f 3.7f 0.000353265f 7898.3f 12.23209f, add_from_left(1.238, 3.7, 0.000353265, 7898.3, 12.23209));EXPECT_EQ(1.238f 3.7f 0.000353265f 7898.3f 12.23209f, add_from_right(1.238, 3.7, 0.000353265, 7898.3, 12.23209));
//
}TEST(AddFuncTest, doubleVSfloat) {printf(AddFuncTest: float sum %f\n, 1.238f 3.7f 0.000353265f 7898.3f 12.23209f);printf(AddFuncTest: double sum %f\n, 12.23209 7898.3 0.000353265 3.7 1.238);EXPECT_EQ(1.238f 3.7f 0.000353265f 7898.3f 12.23209f, add_from_left(1.238, 3.7, 0.000353265, 7898.3, 12.23209));EXPECT_EQ(1.238 3.7 0.000353265 7898.3 12.23209, add_from_right(1.238, 3.7, 0.000353265, 7898.3, 12.23209));
//
}TEST(SumFuncTest, twoNumbers){EXPECT_EQ(sum(3,4),7);EXPECT_EQ(27, sum(9, 18));
}GTEST_API_ int main(int argc, char** argv) {printf(Running main() from %s\n, __FILE__);testing::InitGoogleTest(argc, argv);return RUN_ALL_TESTS();
} Makefile
EXE : hello_gtest_ex hello_gtest_add_int_int
all: $(EXE)%: %.cppg -O0 -fno-toplevel-reorder $ -o $ $(INC) $(LD_FLAGS)INC : -I../googletest/googletest/include/
LD_FLAGS : -L../googletest/build/lib/ -lgtest -lgtest_main.PHONY: clean
clean:-rm -rf $(EXE) 2示例与源码分析
使用最简单的测试示例聚焦googletest本身的代码逻辑
观察点main 函数如何调用到 TEST(...){...} 这种结构中的代码
两种方式互相印证
方式1通过编译器的预编译指令 g -E ... 生成展开代码;
方式2通过跟踪源代码来份些TEST等的展开结果 2.1 TEST
示例代码如上
simple_gtest.cpp #include gtest/gtest.hint add_int_int(int a, int b){return ab;
}TEST(SumFuncTest, twoNumbers){EXPECT_EQ(add_int_int(3,4),7);
} 方式1:
g -E simple_gtest.cpp -o simple_gtest.i
展开后simple_gtest.i文件有8W多行但是其中对我们理解有意义的也就最尾巴上的几行 int add_int_int(int a, int b){return ab;
}static_assert(sizeof(SumFuncTest) 1, test_suite_name must not be empty);
static_assert(sizeof(twoNumbers) 1, test_name must not be empty); class SumFuncTest_twoNumbers_Test : public ::testing::Test {
public: SumFuncTest_twoNumbers_Test() {}
private:virtual void TestBody(); static ::testing::TestInfo* const test_info_ __attribute__ ((unused)); SumFuncTest_twoNumbers_Test(SumFuncTest_twoNumbers_Test const ) delete; void operator(SumFuncTest_twoNumbers_Test const ) delete;
}; ::testing::TestInfo* const SumFuncTest_twoNumbers_Test::test_info_ ::testing::internal::MakeAndRegisterTestInfo( SumFuncTest, twoNumbers, nullptr, nullptr, ::testing::internal::CodeLocation(simple_gtest.cpp, 8), (::testing::internal::GetTestTypeId()), ::testing::internal::SuiteApiResolver ::testing::Test::GetSetUpCaseOrSuite(simple_gtest.cpp, 8), ::testing::internal::SuiteApiResolver ::testing::Test::GetTearDownCaseOrSuite(simple_gtest.cpp, 8), new ::testing::internal::TestFactoryImplSumFuncTest_twoNumbers_Test); void SumFuncTest_twoNumbers_Test::TestBody()
{switch (0) case 0: default: if (const ::testing::AssertionResult gtest_ar (::testing::internal::EqHelper::Compare(add_int_int(3,4), 7, add_int_int(3,4), 7))) ; else ::testing::internal::AssertHelper(::testing::TestPartResult::kNonFatalFailure, simple_gtest.cpp, 9, gtest_ar.failure_message()) ::testing::Message();
}
分析这段代码会发现
TEST被展开成为了一个 class SumFuncTest_twoNumbers_Test
它有一个成员函数 TestBody(){....}
观察上述代码中最后一个函数体void SumFuncTest_twoNumbers_Test::TestBody()
其中出现了被测试的函数等。
这说明这个函数体中的代码才是是被测试内容而其外围都是框架。
框架部分只需要把这中类的一个实例添加到某个链表中然后依次迭代执行每个类的 TestBody成员函数既可以完成测试任务。
本例中的 class 如下 通过方法2.来验证一下展开的结果
第一部分class 宏
关联TEST宏我们可以找到如下内容 #define TEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name)#define GTEST_TEST(test_suite_name, test_name) \GTEST_TEST_(test_suite_name, test_name, ::testing::Test, \::testing::internal::GetTestTypeId())// Expands to the name of the class that implements the given test.
#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \test_suite_name##_##test_name##_Test// Helper macro for defining tests.
#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id) \static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) 1, \test_suite_name must not be empty); \static_assert(sizeof(GTEST_STRINGIFY_(test_name)) 1, \test_name must not be empty); \class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \: public parent_class { \public: \GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() default; \~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override default; \GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \(const GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) ) delete; \GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) operator( \const GTEST_TEST_CLASS_NAME_(test_suite_name, \test_name) ) delete; /* NOLINT */ \GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \(GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) ) noexcept delete; \GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) operator( \GTEST_TEST_CLASS_NAME_(test_suite_name, \test_name) ) noexcept delete; /* NOLINT */ \\private: \void TestBody() override; \static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \}; \\::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \test_name)::test_info_ \::testing::internal::MakeAndRegisterTestInfo( \#test_suite_name, #test_name, nullptr, nullptr, \::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \::testing::internal::SuiteApiResolver \parent_class::GetSetUpCaseOrSuite(__FILE__, __LINE__), \::testing::internal::SuiteApiResolver \parent_class::GetTearDownCaseOrSuite(__FILE__, __LINE__), \new ::testing::internal::TestFactoryImplGTEST_TEST_CLASS_NAME_( \test_suite_name, test_name)); \void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody() 其中的如下两行
class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
: public parent_class { \
TEST 的宏充分展开后会根据TEST(X,Y) 括号中的X、Y字串定义一个完整的类并且包含成员函数: TestBody()
但是展开的内容中没有这个函数的函数体。
这个函数体正好就是TEST(X,Y){Z} 中{Z}的这个部分即 TestBody(){Z}
只需要在整个测试系统中讲上面展开生成的class的一个实例insert进一个链表中并依次迭代执行链表的每一对象的成员函数 TestBody(){Z}即可达到测试目的。
第二部分函数体中的宏
关于 EXPECT_EQ我们会发现如下定义
#define EXPECT_EQ(val1, val2) \EXPECT_PRED_FORMAT2(::testing::internal::EqHelper::Compare, val1, val2)
而其中的 EXPECT_PRED_FORMAT2 又被展开为如下
// Binary predicate assertion macros.
#define EXPECT_PRED_FORMAT2(pred_format, v1, v2) \GTEST_PRED_FORMAT2_(pred_format, v1, v2, GTEST_NONFATAL_FAILURE_)
又 GTEST_PRED_FORMAT2_ 被定义为
#define GTEST_PRED_FORMAT2_(pred_format, v1, v2, on_failure) \GTEST_ASSERT_(pred_format(#v1, #v2, v1, v2), on_failure)
而且其中的 GTEST_ASSERT_ 被展开为
#define GTEST_ASSERT_(expression, on_failure) \GTEST_AMBIGUOUS_ELSE_BLOCKER_ \if (const ::testing::AssertionResult gtest_ar (expression)) \; \else \on_failure(gtest_ar.failure_message())
其中 GTEST_AMBIGUOUS_ELSE_BLOCKER_ 展开为
#define GTEST_AMBIGUOUS_ELSE_BLOCKER_ \switch (0) \case 0: \default: // NOLINT 于是得到函数体为 总之只需要调用这个 TestBody() 函数即可完成测试任务。 2.2 TEST_F 2.2.1 小示例编译与运行
保持关于 TEST 宏分析的记忆我们以一个简单的示例来分析 TEST_F 宏
#include gtest/gtest.hclass SampleTestWithFixture : public ::testing::Test {
protected:void SetUp() override {a_ 1;b_ 2;}int a_;int b_;
};TEST_F(SampleTestWithFixture, Case2) {a_ 3;EXPECT_EQ(a_ b_, 5);
}Makefile:
EXE : hello_gtest_f
all: $(EXE)%: %.cppg -g -fno-toplevel-reorder $ -o $ $(INC) $(LD_FLAGS)# g -E hello_gtest_f.cpp -I ../googletest/googletest/include/ -o hello_gtest_f.i
#g -g -fno-toplevel-reorder $ -o $ $(INC) $(LD_FLAGS)INC : -I../../googletest/googletest/include/
LD_FLAGS : -L../../googletest/build_dbg/lib/ -lgtest -lgtest_main.PHONY: clean
clean:-rm -rf $(EXE)
编译确保能够正确运行
$ make
$ ./hello_gtest_f 2.2.2 TEST_F 宏展开分析
$ g -E hello_gtest_f.cpp -I ../googletest/googletest/include/ -o hello_gtest_f.i
生成的预处理后的文件 hello_gtest_f.i 主要内容还是在文件的尾巴上摘录调整格式如下
class SampleTestWithFixture : public ::testing::Test {
protected:void SetUp() override {a_ 1;b_ 2;}int a_;int b_;
};static_assert(sizeof(SampleTestWithFixture) 1, test_suite_name must not be empty);
static_assert(sizeof(Case2) 1, test_name must not be empty);class SampleTestWithFixture_Case2_Test : public SampleTestWithFixture{
public:SampleTestWithFixture_Case2_Test() default;~SampleTestWithFixture_Case2_Test() override default;SampleTestWithFixture_Case2_Test(const SampleTestWithFixture_Case2_Test) delete;SampleTestWithFixture_Case2_Test operator( const SampleTestWithFixture_Case2_Test) delete;SampleTestWithFixture_Case2_Test(SampleTestWithFixture_Case2_Test ) noexcept delete;SampleTestWithFixture_Case2_Test operator(SampleTestWithFixture_Case2_Test ) noexcept delete;private: void TestBody() override;static ::testing::TestInfo* const test_info_ __attribute__((unused));
};::testing::TestInfo* const SampleTestWithFixture_Case2_Test::test_info_::testing::internal::MakeAndRegisterTestInfo(SampleTestWithFixture,Case2,nullptr,nullptr,::testing::internal::CodeLocation(hello_gtest_f.cpp, 27),(::testing::internal::GetTypeIdSampleTestWithFixture()),::testing::internal::SuiteApiResolver SampleTestWithFixture::GetSetUpCaseOrSuite(hello_gtest_f.cpp, 27),::testing::internal::SuiteApiResolver SampleTestWithFixture::GetTearDownCaseOrSuite(hello_gtest_f.cpp, 27),new ::testing::internal::TestFactoryImplSampleTestWithFixture_Case2_Test);void SampleTestWithFixture_Case2_Test::TestBody()
{a_ 3;switch (0)case 0:default:if (const ::testing::AssertionResult gtest_ar (::testing::internal::EqHelper::Compare( a_ b_ , 5 , a_ b_ , 5 )));else::testing::internal::AssertHelper(::testing::TestPartResult::kNonFatalFailure, hello_gtest_f.cpp, 29, gtest_ar.failure_message()) ::testing::Message();
} 跟 TEST 宏的展开类似组合 TEST_F(X,Y) 的两个参数构成一个新的类
class X_Y_Test :public SampleTestWithFixture{
...
... TestBody()
}
宏展开的新类中也有一个成员函数 TestBody() 其中 SampleTestWithFixture 是自己定义的类会被 X_Y_Test 类共有继承走。
而 TEST_F(...){body} 的类似函数体的部分 {body}也同样被安排成为了 TestBody函数的函数体。
接下来gtest框架会通过成员 X_Y_Test::test_info_ 的静态赋值过程将本测试用例挂进系统的代运行链表届时依次迭代 调用 X_Y_Test::TestBody(); 实现测试感兴趣代码的目的。 2.2.3 总结 TEST_F
TEST_F的意图
TEST_F的目的是为了把关系密切的测试问题汇总到一个class中来进行测试可以共用同一个类的对象的上下文成员数据。 TEST_F 中成员函数的执行顺序
那么成员函数 Setup( ) 在什么时候执行呢
先说答案 1 X_Y_Test() 构造函数//c 语法 2 Setup(); //数据预备资源申请 3 TestBody(); //测试部分 4 TearDown(); //资源释放 5 X_Y_Test() 析构函数//c 语法
改造刚才的示例
#include gtest/gtest.hclass SampleTestWithFixture : public ::testing::Test {
public:
SampleTestWithFixture(){std::coutconstruct_STWFstd::endl;}
~SampleTestWithFixture(){std::coutdestruct_STWFstd::endl;}
protected:void SetUp() override {std::cout Hello setupupup()000std::endl;a_ 1;b_ 2;std::cout Hello setupupup()111std::endl;}void TearDown() override {std::cout Hello teardownnn()000std::endl;a_ 4;b_ 5;std::cout Hello teardownnn()111std::endl;}int a_;int b_;
};TEST_F(SampleTestWithFixture, Case2) {std::cout test_f Casess222std::endl;a_ 3;EXPECT_EQ(a_ b_, 5);
}
编译运行 TEST_F函数体中的部分的一些宏跟TEST中的一样展开成为一些比较语句。 2.3 TEST_P
2.3.1 可运行示例
#include gtest/gtest.hnamespace TTT
{
namespace testing
{
int g_env_switch 0;class BasicTestFixture : public ::testing::TestWithParamint
{
public:BasicTestFixture() {}void SetUp(){g_env_switch GetParam();std::coutBTF_SetUp() gesg_env_switchstd::endl;}void TearDown(){}
};#define OK 0
#define FAIL 1int envCheckFunc(void)
{if(g_env_switch 0) {return OK;}else {return FAIL;}
}TEST_P(BasicTestFixture, BasicTest)
{ASSERT_EQ(envCheckFunc(), OK);
}INSTANTIATE_TEST_SUITE_P(configSwitch, BasicTestFixture, ::testing::Values(1, 0));
//INSTANTIATE_TEST_SUITE_P(failSwitch, BasicTestFixture, ::testing::Values(2, 3));}
}
Makefile
EXE : hello_gtest_pall: $(EXE)%: %.cppg -g -fno-toplevel-reorder $ -o $ $(INC) $(LD_FLAGS)# g -E hello_gtest_p.cpp -I ../googletest/googletest/include/ -o hello_gtest_p.i
#g -g -fno-toplevel-reorder $ -o $ $(INC) $(LD_FLAGS)INC : -I../../googletest/googletest/include/
LD_FLAGS : -L../../googletest/build_dbg/lib/ -lgtest -lgtest_main.PHONY: clean
clean:-rm -rf $(EXE)
编译执行
因为故意藏了一个逻辑错误所以第二个参数时会测试失败 2.3.2 无实例化宏的预编译
注释掉程序中的所有 INSTANTIATE_TEST_SUITE_P 的行不厌其烦地再贴一次
#include gtest/gtest.hnamespace TTT
{
namespace testing
{
int g_env_switch 0;class BasicTestFixture : public ::testing::TestWithParamint
{
public:BasicTestFixture() {}void SetUp(){g_env_switch GetParam();std::coutBTF_SetUp() gesg_env_switchstd::endl;}void TearDown(){}
};#define OK 0
#define FAIL 1int envCheckFunc(void)
{if(g_env_switch 0) {return OK;}else {return FAIL;}
}TEST_P(BasicTestFixture, BasicTest)
{ASSERT_EQ(envCheckFunc(), OK);
}//INSTANTIATE_TEST_SUITE_P(configSwitch, BasicTestFixture, ::testing::Values(1, 0));
//INSTANTIATE_TEST_SUITE_P(failSwitch, BasicTestFixture, ::testing::Values(2, 3));}
}g -E hello_gtest_p.cpp -I ../googletest/googletest/include/ -o hello_gtest_p.i
这时候预编译后生成的代码如下
namespace TTT
{
namespace testing
{
int g_env_switch 0;class BasicTestFixture : public ::testing::TestWithParamint
{
public:BasicTestFixture() {}void SetUp(){g_env_switch GetParam();std::coutBTF_SetUp() gesg_env_switchstd::endl;}void TearDown(){}
};int envCheckFunc(void)
{if(g_env_switch 0) {return 0;}else {return 1;}
}class BasicTestFixture_BasicTest_Test : public BasicTestFixture, private ::testing::internal::GTestNonCopyable {
public:BasicTestFixture_BasicTest_Test() {}void TestBody() override;
private:static int AddToRegistry(){::testing::UnitTest::GetInstance()-parameterized_test_registry().GetTestSuitePatternHolderBasicTestFixture( BasicTestFixture, ::testing::internal::CodeLocation(hello_gtest_p.cpp, 35))-AddTestPattern( BasicTestFixture,BasicTest,new ::testing::internal::TestMetaFactoryBasicTestFixture_BasicTest_Test(),::testing::internal::CodeLocation(hello_gtest_p.cpp, 35));return 0;}static int gtest_registering_dummy_ __attribute__((unused));
};int BasicTestFixture_BasicTest_Test::gtest_registering_dummy_ BasicTestFixture_BasicTest_Test::AddToRegistry();void BasicTestFixture_BasicTest_Test::TestBody()
{switch (0)case 0:default:if (const ::testing::AssertionResult gtest_ar (::testing::internal::EqHelper::Compare(envCheckFunc(), 0, envCheckFunc(), 0)));elsereturn ::testing::internal::AssertHelper(::testing::TestPartResult::kFatalFailure, hello_gtest_p.cpp, 37, gtest_ar.failure_message()) ::testing::Message();
}
没有实例化宏 的代码展开到被测试类的 TestBody()函数后就停止了如上代码中最后一个函数的定义。 2.3.3 有实例化宏的预编译
多了这两句
INSTANTIATE_TEST_SUITE_P(configSwitch, BasicTestFixture, ::testing::Values(1, 0));
INSTANTIATE_TEST_SUITE_P(failSwitch, BasicTestFixture, ::testing::Values(2, 3)); namespace TTT
{
namespace testing
{
int g_env_switch 0;class BasicTestFixture : public ::testing::TestWithParamint
{
public:BasicTestFixture() {}void SetUp(){g_env_switch GetParam();std::coutBTF_SetUp() gesg_env_switchstd::endl;}void TearDown(){}
};int envCheckFunc(void)
{if(g_env_switch 0) {return 0;}else {return 1;}
}class BasicTestFixture_BasicTest_Test : public BasicTestFixture, private ::testing::internal::GTestNonCopyable {
public:BasicTestFixture_BasicTest_Test() {}void TestBody() override;private:static int AddToRegistry(){::testing::UnitTest::GetInstance()-parameterized_test_registry().GetTestSuitePatternHolderBasicTestFixture( BasicTestFixture, ::testing::internal::CodeLocation(hello_gtest_p.cpp, 35))-AddTestPattern( BasicTestFixture,BasicTest,new ::testing::internal::TestMetaFactoryBasicTestFixture_BasicTest_Test(),::testing::internal::CodeLocation(hello_gtest_p.cpp,35));return 0;}static int gtest_registering_dummy_ __attribute__((unused));
};int BasicTestFixture_BasicTest_Test::gtest_registering_dummy_ BasicTestFixture_BasicTest_Test::AddToRegistry();
void BasicTestFixture_BasicTest_Test::TestBody()
{switch (0)case 0:default:if (const ::testing::AssertionResult gtest_ar (::testing::internal::EqHelper::Compare( envCheckFunc(), 0, envCheckFunc(), 0)));elsereturn ::testing::internal::AssertHelper(::testing::TestPartResult::kFatalFailure, hello_gtest_p.cpp, 37, gtest_ar.failure_message()) ::testing::Message();
}
//TEST_P(X, Y, ...){}
// 跟 TEST_F的展开比较接近同样是将 TEST_P(){...} 的{...} 部分作为TestBody的函数体
// 但一个重要不懂的地方在于TEST_P 展开为被测试模式或模版真正注册近被执行队列是INSTANTIATE_TEST_SUITE_P的工作。//INSTANTIATE_TEST_SUITE_P(X, Y, ...)的展开位三个函数
//参数容器函数gtest_XY_EvaluGenerator_ 测试参数值
//被测试类函数gtest_XY_EvalGenerateName_ 测试参数类型
//测试类压栈函数gtest_XY_dummy_ 将测试类实例化后 push进带测试队列中通过调用 AddTestSuiteInstantiation//展开INSTANTIATE_TEST_SUITE_P(configSwitch, BasicTestFixture, ::testing::Values(1, 0));static ::testing::internal::ParamGeneratorBasicTestFixture::ParamType gtest_configSwitchBasicTestFixture_EvalGenerator_()
{return::testing::Values(1, 0);
}static ::std::string gtest_configSwitchBasicTestFixture_EvalGenerateName_( const ::testing::TestParamInfoBasicTestFixture::ParamType info)
{if (::testing::internal::AlwaysFalse()) {::testing::internal::TestNotEmpty(::testing::internal::DefaultParamNameBasicTestFixture::ParamType);auto t std::make_tuple(::testing::Values(1, 0));static_assert(std::tuple_sizedecltype(t)::value 2, Too Many Args!);}return ((::testing::internal::DefaultParamNameBasicTestFixture::ParamType))(info);
}static int gtest_configSwitchBasicTestFixture_dummy_ __attribute__((unused)) ::testing::UnitTest::GetInstance()-parameterized_test_registry().GetTestSuitePatternHolderBasicTestFixture(BasicTestFixture, ::testing::internal::CodeLocation(hello_gtest_p.cpp, 40))-AddTestSuiteInstantiation(configSwitch,gtest_configSwitchBasicTestFixture_EvalGenerator_,gtest_configSwitchBasicTestFixture_EvalGenerateName_,hello_gtest_p.cpp,40);//展开INSTANTIATE_TEST_SUITE_P(failSwitch, BasicTestFixture, ::testing::Values(2, 3));static ::testing::internal::ParamGeneratorBasicTestFixture::ParamType gtest_failSwitchBasicTestFixture_EvalGenerator_()
{return::testing::Values(2, 3);
}static ::std::string gtest_failSwitchBasicTestFixture_EvalGenerateName_( const ::testing::TestParamInfoBasicTestFixture::ParamType info)
{if (::testing::internal::AlwaysFalse()) {::testing::internal::TestNotEmpty(::testing::internal::DefaultParamNameBasicTestFixture::ParamType);auto t std::make_tuple(::testing::Values(2, 3));static_assert(std::tuple_sizedecltype(t)::value 2, Too Many Args!);}return ((::testing::internal::DefaultParamNameBasicTestFixture::ParamType))(info);
}static int gtest_failSwitchBasicTestFixture_dummy_ __attribute__((unused)) ::testing::UnitTest::GetInstance()-parameterized_test_registry().GetTestSuitePatternHolderBasicTestFixture(BasicTestFixture, ::testing::internal::CodeLocation(hello_gtest_p.cpp, 41))-AddTestSuiteInstantiation(failSwitch,gtest_failSwitchBasicTestFixture_EvalGenerator_,gtest_failSwitchBasicTestFixture_EvalGenerateName_,hello_gtest_p.cpp,41);}
}2.3.4 分析 TEST_P 和
TEST_P(X, Y, ...){...}的展开 跟 TEST_F的展开比较接近继承用户自定义类后定义一个新类含有成员函数 TestBody同样是将 TEST_P(){...} 的{...} 部分作为TestBody的函数体
但一个重要不同的地方在于TEST_P 展开为被测试模式或模版真正注册近被执行队列是INSTANTIATE_TEST_SUITE_P的工作。 INSTANTIATE_TEST_SUITE_P(X, Y, ...)的展开位三个函数
1参数容器函数gtest_XY_EvaluGenerator_ 测试参数值
2被测试类函数gtest_XY_EvalGenerateName_ 测试参数类型
3测试类压栈函数gtest_XY_dummy_ 将测试类实例化后 push进带测试队列中通过调用 AddTestSuiteInstantiation压栈入队等待main函数依次迭代调用各个类实例的 TestBody()成员函数完成测试任务。 而其中的SetUp(), TearDown()等成员函数的调用跟TEST_F的调用时机相同。 3. 总结
掌握 googletest的使用 首先需要理解TESTXXX(){...}结构中{...}会被展开为一个类的成员函数 TestBody(){...} 的函数体。 其次掌握Setup,TearDown的调用时机 然后对各种判别宏有一定掌握比如 EXPECT_EQ 最后掌握 TEST_P de 参数的各种形式的使用方式