GTest源码分析——用例注册与执行过程

GTest源码分析——用例注册与执行过程

google/googletest | DeepWiki

Google Test(GTest)使用方法和源码解析——自动调度机制分析_&test::testbody-CSDN博客

本文不是按照阅读源码时的分析顺序,而是在阅读源码后,将涉及到的数据结构、函数放在最前面,最后再分析执行流程的。所以在分析执行流程时,不再分析函数逻辑了,不记得了就在上文找。

本文给出的源码,都经过了删减,只展示部分逻辑。

HandleExceptionsInMethodIfSupported() 函数

兼容C++异常/Windows SEH异常的函数,内部就是帮你执行 object::method()

template <class T, typename Result>
Result HandleExceptionsInMethodIfSupported(T* object, Result (T::*method)(),
                                           const char* location) {
  if (internal::GetUnitTestImpl()->catch_exceptions()) {
	// ...
    return (object->*method)();
  }
}

UnitTest 类

就是一个存储了一堆 TestSuites 的容器。这个类对象以单例形式存在,是GTest框架中其他类之间沟通的桥梁。

这个类采用 Pimpl 设计,所以还有一个 UnitTestImpl 实现类。

UnitTestImpl::AddTestInfo() 函数

void AddTestInfo(internal::SetUpTestSuiteFunc set_up_tc,
                 internal::TearDownTestSuiteFunc tear_down_tc,
                 TestInfo* test_info) {
    GetTestSuite(test_info->test_suite_name_, test_info->type_param(),
                 set_up_tc, tear_down_tc)
        ->AddTestInfo(test_info);
}

UniTestImpl::GetTestSuite() 函数

UnitTestImpl::GetTestSuite() 会尝试查找是否存在已有的同名 TestSuite 对象,没有就新建一个:

image

UnitTestImpl::RunAllTests() 函数

bool UnitTestImpl::RunAllTests() {
  // 启动监听器
  TestEventListener* repeater = listeners()->repeater();
  repeater->OnTestProgramStart(*parent_);

  // How many times to repeat the tests?  We don't want to repeat them
  // when we are inside the subprocess of a death test.
  const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG_GET(repeat);

  // Repeats forever if the repeat count is negative.
  const bool gtest_repeat_forever = repeat < 0;

  // 每轮循环是一遍全量测试
  for (int i = 0; gtest_repeat_forever || i != repeat; i++) {
    // Tells the unit test event listeners that the tests are about to start.
    repeater->OnTestIterationStart(*parent_, i);

    // Runs each test suite if there is at least one test to run.
    if (has_tests_to_run) {
      // Sets up all environments beforehand. If test environments aren't
      // recreated for each iteration, only do so on the first iteration.
      if (i == 0 || recreate_environments_when_repeating) {
        repeater->OnEnvironmentsSetUpStart(*parent_);
        ForEach(environments_, SetUpEnvironment);
        repeater->OnEnvironmentsSetUpEnd(*parent_);
      }

      // Runs the tests only if there was no fatal failure or skip triggered
      // during global set-up.
      if (Test::IsSkipped()) {
        // Emit diagnostics when global set-up calls skip, as it will not be
        // emitted by default.
        TestResult& test_result =
            *internal::GetUnitTestImpl()->current_test_result();
        for (int j = 0; j < test_result.total_part_count(); ++j) {
          const TestPartResult& test_part_result =
              test_result.GetTestPartResult(j);
        }
        fflush(stdout);
      } else if (!Test::HasFatalFailure()) {
        // 遍历所有 TestSuite 并调用其 Run 方法
        for (int test_index = 0; test_index < total_test_suite_count();
             test_index++) {
          GetMutableSuiteCase(test_index)->Run(); // 执行测试
          if (GTEST_FLAG_GET(fail_fast) &&
              GetMutableSuiteCase(test_index)->Failed()) {
            for (int j = test_index + 1; j < total_test_suite_count(); j++) {
              GetMutableSuiteCase(j)->Skip();
            }
            break;
          }
        }
      } else if (Test::HasFatalFailure()) {
        // If there was a fatal failure during the global setup then we know we
        // aren't going to run any tests. Explicitly mark all of the tests as
        // skipped to make this obvious in the output.
        for (int test_index = 0; test_index < total_test_suite_count();
             test_index++) {
          GetMutableSuiteCase(test_index)->Skip();
        }
      }

      // Tears down all environments in reverse order afterwards. If test
      // environments aren't recreated for each iteration, only do so on the
      // last iteration.
      if (i == repeat - 1 || recreate_environments_when_repeating) {
        repeater->OnEnvironmentsTearDownStart(*parent_);
        std::for_each(environments_.rbegin(), environments_.rend(),
                      TearDownEnvironment);
        repeater->OnEnvironmentsTearDownEnd(*parent_);
      }
    }

    // Tells the unit test event listener that the tests have just finished.
    repeater->OnTestIterationEnd(*parent_, i);

    // Gets the result and clears it.
    if (!Passed()) {
      failed = true;
    }
  }

  repeater->OnTestProgramEnd(*parent_);
  // Destroy environments in normal code, not in static teardown.
  bool delete_environment_on_teardown = true;
  if (delete_environment_on_teardown) {
    ForEach(environments_, internal::Delete<Environment>);
    environments_.clear();
  }

  return !failed;
}

TestFactory 类

其是一个类工厂,利用多态和模板:

// Defines the abstract factory interface that creates instances
// of a Test object.
class TestFactoryBase {
 public:
  virtual ~TestFactoryBase() = default;

  // Creates a test instance to run. The instance is both created and destroyed
  // within TestInfoImpl::Run()
  virtual Test* CreateTest() = 0;

 protected:
  TestFactoryBase() {}

 private: // 禁止拷贝
  TestFactoryBase(const TestFactoryBase&) = delete;
  TestFactoryBase& operator=(const TestFactoryBase&) = delete;
};

// This class provides implementation of TestFactoryBase interface.
// It is used in TEST and TEST_F macros.
template <class TestClass>
class TestFactoryImpl : public TestFactoryBase {
 public:
  Test* CreateTest() override { return new TestClass; }
};

Test 类

代表一个测试用例本身。是纯粹的测试逻辑。

Test::Run() 函数

就是执行宏生成/自己写的 Test 子类的钩子函数:SetUp() --> TestBody() --> TearDown()

void Test::Run() {
  internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
  impl->os_stack_trace_getter()->UponLeavingGTest();
  internal::HandleExceptionsInMethodIfSupported(this, &Test::SetUp, "SetUp()");
  // We will run the test only if SetUp() was successful and didn't call
  // GTEST_SKIP().
  if (!HasFatalFailure() && !IsSkipped()) {
    impl->os_stack_trace_getter()->UponLeavingGTest();
    internal::HandleExceptionsInMethodIfSupported(this, &Test::TestBody,
                                                  "the test body");
  }

  // However, we want to clean up as much as possible.  Hence we will
  // always call TearDown(), even if SetUp() or the test body has
  // failed.
  impl->os_stack_trace_getter()->UponLeavingGTest();
  internal::HandleExceptionsInMethodIfSupported(this, &Test::TearDown,
                                                "TearDown()");
}

TestInfo 类

TestInfo 类存储了一个测试的名字、是否应该被执行等元信息,并负责管理用户的测试类的生命周期。

其地位是连接 Test 类与 TestSuite 类,持有注入的工厂实例来负责 Test 类实例的构造与销毁。

TestInfo::Run() 函数

该函数负责创建用户通过 TEST/TEST_F 宏生成的测试类的对象,并执行该对象的 TestBody() 函数并报告执行结果,最后释放内存。

void TestInfo::Run() {
  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
  UnitTest::GetInstance()->set_current_test_info(this);

  // Notifies the unit test event listeners that a test is about to start.
  repeater->OnTestStart(*this);
  result_.set_start_timestamp(internal::GetTimeInMillis());
  UnitTest::GetInstance()->UponLeavingGTest();

  // 创建Test对象
  Test* const test = internal::HandleExceptionsInMethodIfSupported(
      factory_, &internal::TestFactoryBase::CreateTest,
      "the test fixture's constructor");

  // 执行测试
  if (!Test::HasFatalFailure() && !Test::IsSkipped()) {
    test->Run();
  }

  if (test != nullptr) {
    // Deletes the test object.
    UnitTest::GetInstance()->UponLeavingGTest();
    internal::HandleExceptionsInMethodIfSupported(
        test, &Test::DeleteSelf_, "the test fixture's destructor");
  }

  // Notifies the unit test event listener that a test has just finished.
  repeater->OnTestEnd(*this);
  UnitTest::GetInstance()->set_current_test_info(nullptr);
}

TestSuite 类

就是一个存储了一堆 TestInfo 的容器。

TestSuite::AddTestInfo() 函数

void TestSuite::AddTestInfo(TestInfo* test_info) {
  test_info_list_.push_back(test_info);
  test_indices_.push_back(static_cast<int>(test_indices_.size()));
}

TestSuite::Run() 函数

void TestSuite::Run() {
  UnitTest::GetInstance()->set_current_test_suite(this);

  TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();
  repeater->OnTestSuiteStart(*this);

  UnitTest::GetInstance()->UponLeavingGTest();
  // 调用绑定的 SetUp 方法
  internal::HandleExceptionsInMethodIfSupported(
      this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()");

  // 开始执行测试
  for (int i = 0; i < total_test_count(); i++) {
    if (skip_all) {
      GetMutableTestInfo(i)->Skip();
    } else {
      GetMutableTestInfo(i)->Run();
    }
    if (GTEST_FLAG_GET(fail_fast) &&
        GetMutableTestInfo(i)->result()->Failed()) {
      for (int j = i + 1; j < total_test_count(); j++) {
        GetMutableTestInfo(j)->Skip();
      }
      break;
    }
  }

  UnitTest::GetInstance()->UponLeavingGTest();
  // 调用绑定的 TearDown 方法
  internal::HandleExceptionsInMethodIfSupported(
      this, &TestSuite::RunTearDownTestSuite, "TearDownTestSuite()");

  repeater->OnTestSuiteEnd(*this);
  UnitTest::GetInstance()->set_current_test_suite(nullptr);
}

TEST / TEST_F 宏

这两个宏会展开为:

#define GTEST_TEST(test_suite_name, test_name)             \
  GTEST_TEST_(test_suite_name, test_name, ::testing::Test, \
              ::testing::internal::GetTestTypeId())

#define GTEST_TEST_F(test_fixture, test_name)        \
  GTEST_TEST_(test_fixture, test_name, test_fixture, \
              ::testing::internal::GetTypeId<test_fixture>())

可以看到,其实使用 TEST 还是 TEST_F 本质都是一样的,只不过差在继承关系和是否重写了 SetUp()/TearDown() 方法:

classDiagram TEST <|-- TEST宏生成的类 TEST <|-- 用户手动继承的Fixture类 用户手动继承的Fixture类 <|-- TEST_F宏生成的类

GTEST_TEST_ 宏

GTEST_TEST_ 会展开如下:

image

它是为每个“用例函数”生成了一个用例类,类禁用了拷贝和移动语义,继承自 ::testing::Test ,具有一个虚函数 TestBody() 并放在宏最后用于承接 TEST() { ... } 的函数体。且定义了一个静态变量 test_info_ ,利用静态变量在 main 执行之前被初始化的规则,将注册用例的操作 MakeAndRegisterTestInfo() 作为 test_info_ 的初始化过程,从而能自动在程序开始前执行注册逻辑。

MakeAndRegisterTestInfo() 函数

它是就地通过 __FILE____LINE__ 保存了代码位置到 CodeLocation ,通过 TestFactory 创建了 TestInfo ,然后调用 UnitTestImpl::AddTestInfo() 记录这个 TestInfo

// Creates a new TestInfo object and registers it with Google Test;
// returns the created object.
//
// Arguments:
//
//   test_suite_name:  name of the test suite
//   name:             name of the test
//   type_param:       the name of the test's type parameter, or NULL if
//                     this is not a typed or a type-parameterized test.
//   value_param:      text representation of the test's value parameter,
//                     or NULL if this is not a value-parameterized test.
//   code_location:    code location where the test is defined
//   fixture_class_id: ID of the test fixture class
//   set_up_tc:        pointer to the function that sets up the test suite
//   tear_down_tc:     pointer to the function that tears down the test suite
//   factory:          pointer to the factory that creates a test object.
//                     The newly created TestInfo instance will assume
//                     ownership of the factory object.
TestInfo* MakeAndRegisterTestInfo(
    std::string 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(std::move(test_suite_name), name, type_param, value_param,
                   std::move(code_location), fixture_class_id, factory);
  GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
  return test_info;
}

RUN_ALL_TESTS() 函数

在此之前还有个用于解析命令行参数的 InitGoogleTest() ,那个不重要。通过 UniTest 单例来执行:

inline int RUN_ALL_TESTS() { return ::testing::UnitTest::GetInstance()->Run(); }

int UnitTest::Run() {
  // Captures the value of GTEST_FLAG(catch_exceptions).  This value will be
  // used for the duration of the program.
  impl()->set_catch_exceptions(GTEST_FLAG_GET(catch_exceptions));
  }
  return internal::HandleExceptionsInMethodIfSupported(
             impl(), &internal::UnitTestImpl::RunAllTests,
             "auxiliary test code (environments or event listeners)")
             ? 0
             : 1;
}

所以就相当于 UnitTest::impl()->RunAllTests()

其中 impl_ 对象在 UnitTest 单例创建时被创建:

UnitTest::UnitTest() { impl_ = new internal::UnitTestImpl(this); }

UnitTestImpl::RunAllTests() 分析见上文。

整体流程

类图

classDiagram class UnitTest { -std::vector<TestSuite*> test_suites_ -TestEventListeners listeners_ +static UnitTest* GetInstance() +int Run() } class TestSuite { -std::vector<TestInfo*> test_info_list_ +static void SetUpTestSuite() +static void TearDownTestSuite() } class TestInfo { -internal::TestFactoryBase* factory_ -TestResult result_ +Test* CreateTest() } class Test { +virtual void SetUp() +virtual void TearDown() +static bool HasFatalFailure() +static bool HasFailure() #virtual void TestBody() : = 0 } class TestEventListener { «interface» +OnXxx(...) } class Environment { «interface» +virtual void SetUp() : = 0 +virtual void TearDown() : = 0 } UnitTest *-- TestSuite : creates via factory Environment --o UnitTest UnitTest --> TestEventListener TestSuite *-- TestInfo TestInfo --> Test

执行流

graph TD MAIN["main()"] INIT["InitGoogleTest(&argc, &argv)<br>解析命令行参数"] ENV_SETUP["AddGlobalTestEnvironment()<br>注册Environment子类实例"] RUN["RUN_ALL_TESTS()<br>执行测试"] UNITTEST["UnitTest::GetInstance()->Run()"] SUITE_ITER["遍历UnitTest单例中的TestSuite"] SUITE_SETUP["TestSuite::SetUpTestSuite()"] TEST_ITER["遍历TestSuite中的TestInfo"] CREATE["TestInfo::factory_->CreateTest()<br>现场创建Test对象"] SETUP["Test::SetUp()"] BODY["Test::TestBody()"] TEARDOWN["Test::TearDown()"] DELETE["delete test_instance"] SUITE_TEARDOWN["TestSuite::TearDownTestSuite()"] LISTENERS["TestEventListeners::OnTestStart()"] ON_PART["TestEventListeners::OnTestPartResult()"] ON_END["TestEventListeners::OnTestEnd()"] PRINTERS["PrettyUnitTestResultPrinter<br>XmlUnitTestResultPrinter<br>JsonUnitTestResultPrinter"] GEN_TEST_CLASS["TEST/TEST_F<br>生成Test的子类"] MAKE_TEST_INFO["MakeAndRegisterTestInfo<br>创建并注册TestInfo类实例到UnitTest单例"] MAKE_TEST_INFO --> MAIN ENV_SETUP --> RUN CREATE --> LISTENERS LISTENERS --> SETUP DELETE --> ON_END ON_END --> TEST_ITER BODY --> ON_PART subgraph subGraph2 ["Event Broadcasting"] LISTENERS ON_PART ON_END PRINTERS ON_PART --> PRINTERS ON_END --> PRINTERS end subgraph subGraph1 ["Test Execution"] RUN UNITTEST SUITE_ITER SUITE_SETUP TEST_ITER CREATE SETUP BODY TEARDOWN DELETE SUITE_TEARDOWN RUN --> UNITTEST UNITTEST --> SUITE_ITER SUITE_ITER --> SUITE_SETUP SUITE_SETUP --> TEST_ITER TEST_ITER --> CREATE SETUP --> BODY BODY --> TEARDOWN TEARDOWN --> DELETE TEST_ITER --> SUITE_TEARDOWN end subgraph Initialization ["Initialization"] MAIN INIT ENV_SETUP MAIN --> INIT INIT --> ENV_SETUP end subgraph Registration ["Registration"] GEN_TEST_CLASS MAKE_TEST_INFO GEN_TEST_CLASS --> MAKE_TEST_INFO end

总结

类之间的关系

在 GoogleTest 的架构中,类之间的关系是:

  • UnitTest (单例) → 管理多个 TestSuite → 每个包含多个 TestInfo → 每个通过其构造时注入的工厂类实例来创建 Test 实例。
  • 即通过所有属于同一个 text fixture 的用例,每个都对应一个自己的 Test 子类实例和 TestInfo 实例,最终都会存储在同一个 TestSuite 实例中。而所有的 TestSuite 实例又存储在 UnitTest 单例中。

用例注册过程

  1. TEST/TEST_F 宏展开声明了一个最终继承于 Test 的子类
    • 声明了一个虚函数 TestBody()
    • 声明了一个静态成员变量 ::testing::TestInfo* const test_info_
  2. 在类外,利用 MakeAndRegisterTestInfo 初始化了静态成员变量 test_info_
    1. 其中访问 UnitTest 单例会使得在 main 函数执行前就将所有测试用例都注册到 UnitTest 单例中。
  3. 最后输出了 TestBody() 的函数签名,此时会连上我们测试用例的函数体。

用例执行过程

TestSuite::Run() 方法遍历所有 TestInfo,为每个测试:

  1. 调用 SetUpTestSuite() (整个套件执行一次)
  2. 为每个测试创建新的 Test 实例
  3. 调用 Test::SetUp()
  4. 执行 Test::TestBody() (测试逻辑)
  5. 调用 Test::TearDown()
  6. 删除 Test 实例
  7. 调用 TearDownTestSuite() (整个套件执行一次)
posted @ 2025-11-11 11:51  3的4次方  阅读(6)  评论(0)    收藏  举报