gtest源码分析

一、流程分析

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()));
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值