一、前言
“深入解析”对我来说的确有些难度,所以我尽量将我学习到和观察到的gtest内部实现介绍给大家。本文算是抛砖引玉吧,只能是对gtest的整体结构的一些介绍,想要了解更多细节最好的办法还是看gtest源码,如果你看过gtest源码,你会发现里面的注释非常的详细!好了,下面就开始了解gtest吧。
二、从TEST宏开始
前面的文章已经介绍过TEST宏的用法了,通过TEST宏,我们可以非法简单、方便的编写测试案例,比如:
{
EXPECT_EQ( 1 , 1 );
}
我们先不去看TEST宏的定义,而是先使用/P参数将TEST展开。如果使用的是Vistual Studio的话:
1. 选中需要展开的代码文件,右键 - 属性 - C/C++ - Preprocessor
2. Generate Preprocessed File 设置 Without Line Numbers (/EP /P) 或 With Line Numbers (/P)
3. 关闭属性对话框,右键选中需要展开的文件,右键菜单中点击:Compile
编译过后,会在源代码目录生成一个后缀为.i的文件,比如我对上面的代码进行展开,展开后的内容为:
{
public :
FooTest_Demo_Test() {}
private :
virtual void TestBody();
static ::testing::TestInfo * const test_info_;
FooTest_Demo_Test( const FooTest_Demo_Test & );
void operator = ( const FooTest_Demo_Test & );
};
::testing::TestInfo * const FooTest_Demo_Test
::test_info_ =
::testing:: internal ::MakeAndRegisterTestInfo(
" FooTest " , " Demo " , "" , "" ,
(::testing:: internal ::GetTestTypeId()),
::testing::Test::SetUpTestCase,
::testing::Test::TearDownTestCase,
new ::testing:: internal ::TestFactoryImpl < FooTest_Demo_Test > );
void FooTest_Demo_Test::TestBody()
{
switch ( 0 )
case 0 :
if ( const ::testing::AssertionResult
gtest_ar =
(::testing:: internal :: EqHelper < ( sizeof (::testing:: internal ::IsNullLiteralHelper( 1 )) == 1 ) > ::Compare( " 1 " , " 1 " , 1 , 1 )))
;
else
::testing:: internal ::AssertHelper(
::testing::TPRT_NONFATAL_FAILURE,
" .\\gtest_demo.cpp " ,
9 ,
gtest_ar.failure_message()
) = ::testing::Message();
}
展开后,我们观察到:
1. TEST宏展开后,是一个继承自testing::Test的类。
2. 我们在TEST宏里面写的测试代码,其实是被放到了类的TestBody方法中。
3. 通过静态变量test_info_,调用MakeAndRegisterTestInfo对测试案例进行注册。
如下图:
上面关键的方法就是MakeAndRegisterTestInfo了,我们跳到MakeAndRegisterTestInfo函数中:
// 返回创建的TestInfo对象
//
// 参数:
//
// test_case_name: 测试案例的名称
// name: 测试的名称
// test_case_comment: 测试案例的注释信息
// comment: 测试的注释信息
// fixture_class_id: test fixture类的ID
// set_up_tc: 事件函数SetUpTestCases的函数地址
// tear_down_tc: 事件函数TearDownTestCases的函数地址
// factory: 工厂对象,用于创建测试对象(Test)
TestInfo * MakeAndRegisterTestInfo(
const char * test_case_name, const char * name,
const char * test_case_comment, const char * comment,
TypeId fixture_class_id,
SetUpTestCaseFunc set_up_tc,
TearDownTestCaseFunc tear_down_tc,
TestFactoryBase * factory) {
TestInfo * const test_info =
new TestInfo(test_case_name, name, test_case_comment, comment,
fixture_class_id, factory);
GetUnitTestImpl() -> AddTestInfo(set_up_tc, tear_down_tc, test_info);
return test_info;
}