一、流程分析
gtest是谷歌的一个单元测试框架,使用时,main函数的编写大致如下
int main(int argc, char **argv)
{
//...
::testing::InitGoogleTest(&argc, argv);
RUN_ALL_TESTS();
system("pause");
return 0;
}
上述的代码中的核心就是RUN_ALL_TESTS,实现很简单
inline int RUN_ALL_TESTS() {
return ::testing::UnitTest::GetInstance()->Run();
}
而 UnitTest::Run()的核心代码如下
int UnitTest::Run() {
//平台相关的设置以及异常处理
return internal::HandleExceptionsInMethodIfSupported(
impl(),
&internal::UnitTestImpl::RunAllTests,
"auxiliary test code (environments or event listeners)") ? 0 : 1;
}
在函数HandleExceptionsInMethodIfSupported中,最终要返回UnitTestImpl::RunAllTests的调用结果。
UnitTestImpl::RunAllTests的核心代码如下
bool UnitTestImpl::RunAllTests() {
//.....
for (int test_index = 0; test_index < total_test_suite_count();
test_index++) {
GetMutableSuiteCase(test_index)->Run();
//....
}
//.....
}
gtest会先统计测试套件的个数。测试套件就是测试case的集合
其中,TestSuite::Run的核心实现如下
void TestSuite::Run() {
//....
for (int i = 0; i < total_test_count(); i++) {
GetMutableTestInfo(i)->Run();
}
//....
}
然后针对每个测试套件中,有多少个测试case,分别执行每个测试套件中的测试case。测试case是对用户实现的TEST_F的个数进行计数并通过函数total_test_suite_count进行返回。
TestInfo::Run()的核心代码如下
void TestInfo::Run() {
// Creates the test object.
Test* const test = internal::HandleExceptionsInMethodIfSupported(
factory_, &internal::TestFactoryBase::CreateTest,
"the test fixture's constructor");
if (!Test::HasFatalFailure() && !Test::IsSkipped()) {
// This doesn't throw as all user code that can throw are wrapped into
// exception handling code.
test->Run();
}
}
核心代码主要就是创建Test对象并调用Run
到了Run函数,才真正的执行具体的测试case
void Test::Run() {
internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
internal::HandleExceptionsInMethodIfSupported(this, &Test::TestBody, "the test body");
internal::HandleExceptionsInMethodIfSupported(this, &Test::TearDown, "TearDown()");
}
其中,因为用户继承了Test类,所以,SetUp和TearDown由用户自己实现,而TestBody就是TEST_F的函数体,也由用户实现
二、TEST_F分析
#define TEST_F(test_fixture, test_name)\
GTEST_TEST_(test_fixture, test_name, test_fixture, \
::testing::internal::GetTypeId<test_fixture>())
#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_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
test_name)); \
GTEST_DISALLOW_MOVE_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
test_name)); \
\
private: \
void TestBody() override; \
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \
}; \
\
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \ //对TestInfo进行初始化并添加至测试case的vector
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::TestFactoryImpl<GTEST_TEST_CLASS_NAME_( \//TestFactoryImpl是TestFactoryBase的子类
test_suite_name, test_name)>); \
void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()//函数体由用户自行添加
#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ //生成类名
test_suite_name##_##test_name##_Test
TestInfo* MakeAndRegisterTestInfo(
const char* test_suite_name, const char* name, const char* type_param,
const char* value_param, CodeLocation code_location,
TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory) {
TestInfo* const test_info =
new TestInfo(test_suite_name, name, type_param, value_param,
code_location, fixture_class_id, factory);
GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);//添加测试case
return test_info;
}
void TestSuite::AddTestInfo(TestInfo* test_info) {
test_info_list_.push_back(test_info);//添加测试case
test_indices_.push_back(static_cast<int>(test_indices_.size()));
}