Googletest 实现简要分析
借助于 Googletest 測試框架,我們只需編寫測試用例代碼,并定義簡單的 main() 函數,編譯之后并運行即可以把我們的測試用例跑起來。(更詳細的內容可參考 Googletest 入門)。但 main() 函數調用 RUN_ALL_TESTS() 時,是如何找到并運行我們編寫的測試用例代碼的呢?本文嘗試找尋 Googletest 框架背后隱藏的這些秘密。(代碼分析基于 git@github.com:google/googletest.git 的 commit 2134e3fd857d952e03ce76064fad5ac6e9036104 的版本。)
從 TEST 和 TEST_F 說起
googletest/googletest/include/gtest/gtest.h 中 TEST 和 TEST_F 兩個宏的定義如下:
// Note that we call GetTestTypeId() instead of GetTypeId< // ::testing::Test>() here to get the type ID of testing::Test. This // is to work around a suspected linker bug when using Google Test as // a framework on Mac OS X. The bug causes GetTypeId< // ::testing::Test>() to return different values depending on whether // the call is from the Google Test framework itself or from user test // code. GetTestTypeId() is guaranteed to always return the same // value, as it always calls GetTypeId<>() from the Google Test // framework. #define GTEST_TEST(test_suite_name, test_name) \GTEST_TEST_(test_suite_name, test_name, ::testing::Test, \::testing::internal::GetTestTypeId())// Define this macro to 1 to omit the definition of TEST(), which // is a generic name and clashes with some other libraries. #if !GTEST_DONT_DEFINE_TEST #define TEST(test_suite_name, test_name) GTEST_TEST(test_suite_name, test_name) #endif// Defines a test that uses a test fixture. // // The first parameter is the name of the test fixture class, which // also doubles as the test suite name. The second parameter is the // name of the test within the test suite. // // A test fixture class must be declared earlier. The user should put // the test code between braces after using this macro. Example: // // class FooTest : public testing::Test { // protected: // void SetUp() override { b_.AddElement(3); } // // Foo a_; // Foo b_; // }; // // TEST_F(FooTest, InitializesCorrectly) { // EXPECT_TRUE(a_.StatusIsOK()); // } // // TEST_F(FooTest, ReturnsElementCountCorrectly) { // EXPECT_EQ(a_.size(), 0); // EXPECT_EQ(b_.size(), 1); // } // // GOOGLETEST_CM0011 DO NOT DELETE #define TEST_F(test_fixture, test_name)\GTEST_TEST_(test_fixture, test_name, test_fixture, \::testing::internal::GetTypeId<test_fixture>())TEST 和 TEST_F 兩個宏最終都借助于 GTEST_TEST_ 宏完成其工作。
googletest/googletest/include/gtest/internal/gtest-internal.h 中 GTEST_TEST_ 宏的定義如下:
// 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) \class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \: public parent_class { \public: \GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \\private: \virtual void TestBody(); \static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \test_name)); \}; \\::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::TestFactoryImpl<GTEST_TEST_CLASS_NAME_( \test_suite_name, test_name)>); \void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()GTEST_TEST_ 宏定義一個類,它為定義的類實現如下特性:
- 類名:類名由測試套件名、測試用例名和字符串 Test 3 部分組成,不同部分用下劃線分割。如 TEST_F(FooTest, InitializesCorrectly) 和 TEST(FooTest, InitializesCorrectly) 定義的類名為 FooTest_InitializesCorrectly_Test。
- 父類:GTEST_TEST_ 宏定義的類繼承自傳給它的 parent_class 參數類。對于 TEST_F 宏而言,就是測試套件名,對于 TEST 則是 ::testing::Test 類。
- GTEST_TEST_ 宏為它定義的類定義了一個空的默認構造函數。
- GTEST_TEST_ 宏為它定義的類定義并初始化類型為 ::testing::TestInfo* const 的靜態成員變量 test_info_,這個指針變量指向由 ::testing::internal::MakeAndRegisterTestInfo() 函數創建的 ::testing::TestInfo 類型對象。::testing::internal::MakeAndRegisterTestInfo() 函數還會將測試用例的信息注冊給 Google Test。
- GTEST_TEST_ 宏為它定義的類定義 TestBody() 虛函數覆蓋父類的對應函數,函數的函數體正是我們編寫的測試用例代碼,這也就是為什么我們在測試用例代碼體中打斷點時,看到調用棧,代碼是位于名為 TestBody() 的函數中的原因。
- 通過宏 GTEST_DISALLOW_COPY_AND_ASSIGN_ 實現類對象的禁用拷貝構造和賦值。
::testing::internal::MakeAndRegisterTestInfo() 函數定義(googletest/googletest/src/gtest.cc)如下:
// 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(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);return test_info; }測試用例的注冊
在通過 TEST 和 TEST_F 宏定義測試用例時,這些宏實際上將會為測試用例定義一個類,這個類包含一個靜態成員變量,在這個靜態成員變量初始化時,在 ::testing::internal::MakeAndRegisterTestInfo() 函數中向 Google Test 注冊測試用例,具體而言,通過 ::testing::internal::UnitTestImpl::AddTestInfo() 函數注冊測試用例,該函數在 googletest/googletest/src/gtest-internal-inl.h 中定義,定義如下:
// Adds a TestInfo to the unit test.//// Arguments://// 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// test_info: the TestInfo objectvoid AddTestInfo(internal::SetUpTestSuiteFunc set_up_tc,internal::TearDownTestSuiteFunc tear_down_tc,TestInfo* test_info) {// In order to support thread-safe death tests, we need to// remember the original working directory when the test program// was first invoked. We cannot do this in RUN_ALL_TESTS(), as// the user may have changed the current directory before calling// RUN_ALL_TESTS(). Therefore we capture the current directory in// AddTestInfo(), which is called to register a TEST or TEST_F// before main() is reached.if (original_working_dir_.IsEmpty()) {original_working_dir_.Set(FilePath::GetCurrentDir());GTEST_CHECK_(!original_working_dir_.IsEmpty())<< "Failed to get the current working directory.";}GetTestSuite(test_info->test_suite_name(), test_info->type_param(),set_up_tc, tear_down_tc)->AddTestInfo(test_info);}::testing::internal::UnitTestImpl::AddTestInfo() 函數根據測試套件名字等參數獲得測試套件;然后將測試用例添加進測試套件中。
googletest/googletest/src/gtest.cc 中用于獲得測試套件的 ::testing::internal::UnitTestImpl::GetTestSuite() 函數定義如下:
// Finds and returns a TestSuite with the given name. If one doesn't // exist, creates one and returns it. It's the CALLER'S // RESPONSIBILITY to ensure that this function is only called WHEN THE // TESTS ARE NOT SHUFFLED. // // Arguments: // // test_suite_name: name of the test suite // type_param: the name of the test suite's type parameter, or NULL if // this is not a typed or a type-parameterized test suite. // 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 TestSuite* UnitTestImpl::GetTestSuite(const char* test_suite_name, const char* type_param,internal::SetUpTestSuiteFunc set_up_tc,internal::TearDownTestSuiteFunc tear_down_tc) {// Can we find a TestSuite with the given name?const auto test_suite =std::find_if(test_suites_.rbegin(), test_suites_.rend(),TestSuiteNameIs(test_suite_name));if (test_suite != test_suites_.rend()) return *test_suite;// No. Let's create one.auto* const new_test_suite =new TestSuite(test_suite_name, type_param, set_up_tc, tear_down_tc);// Is this a death test suite?if (internal::UnitTestOptions::MatchesFilter(test_suite_name,kDeathTestSuiteFilter)) {// Yes. Inserts the test suite after the last death test suite// defined so far. This only works when the test suites haven't// been shuffled. Otherwise we may end up running a death test// after a non-death test.++last_death_test_suite_;test_suites_.insert(test_suites_.begin() + last_death_test_suite_,new_test_suite);} else {// No. Appends to the end of the list.test_suites_.push_back(new_test_suite);}test_suite_indices_.push_back(static_cast<int>(test_suite_indices_.size()));return new_test_suite; }::testing::internal::UnitTestImpl::GetTestSuite() 函數:
向 TestSuite 添加測試用例的 TestSuite::AddTestInfo() 函數定義(googletest/googletest/src/gtest.cc)如下:
// Adds a test to this test suite. Will delete the test upon // destruction of the TestSuite object. void TestSuite::AddTestInfo(TestInfo* test_info) {test_info_list_.push_back(test_info);test_indices_.push_back(static_cast<int>(test_indices_.size())); }測試用例的執行
在 main() 函數中,通過調用 testing::InitGoogleTest(&argc, argv) 和 RUN_ALL_TESTS() 執行所有的測試用例。testing::InitGoogleTest(&argc, argv) 主要用于解析命令行參數,如 filter 等,這里不再詳細分析。googletest/googletest/include/gtest/gtest.h 中的 RUN_ALL_TESTS() 函數定義如下:
// Use this function in main() to run all tests. It returns 0 if all // tests are successful, or 1 otherwise. // // RUN_ALL_TESTS() should be invoked after the command line has been // parsed by InitGoogleTest(). // // This function was formerly a macro; thus, it is in the global // namespace and has an all-caps name. int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;inline int RUN_ALL_TESTS() {return ::testing::UnitTest::GetInstance()->Run(); }RUN_ALL_TESTS() 函數調用 googletest/googletest/src/gtest.cc 中定義的 UnitTest::Run() 函數執行所有的測試用例:
// Runs all tests in this UnitTest object and prints the result. // Returns 0 if successful, or 1 otherwise. // // We don't protect this under mutex_, as we only support calling it // from the main thread. int UnitTest::Run() {const bool in_death_test_child_process =internal::GTEST_FLAG(internal_run_death_test).length() > 0;// Google Test implements this protocol for catching that a test// program exits before returning control to Google Test://// 1. Upon start, Google Test creates a file whose absolute path// is specified by the environment variable// TEST_PREMATURE_EXIT_FILE.// 2. When Google Test has finished its work, it deletes the file.//// This allows a test runner to set TEST_PREMATURE_EXIT_FILE before// running a Google-Test-based test program and check the existence// of the file at the end of the test execution to see if it has// exited prematurely.// If we are in the child process of a death test, don't// create/delete the premature exit file, as doing so is unnecessary// and will confuse the parent process. Otherwise, create/delete// the file upon entering/leaving this function. If the program// somehow exits before this function has a chance to return, the// premature-exit file will be left undeleted, causing a test runner// that understands the premature-exit-file protocol to report the// test as having failed.const internal::ScopedPrematureExitFile premature_exit_file(in_death_test_child_process? nullptr: internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE"));// 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(catch_exceptions));#if GTEST_OS_WINDOWS// Either the user wants Google Test to catch exceptions thrown by the// tests or this is executing in the context of death test child// process. In either case the user does not want to see pop-up dialogs// about crashes - they are expected.if (impl()->catch_exceptions() || in_death_test_child_process) { # if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT// SetErrorMode doesn't exist on CE.SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); # endif // !GTEST_OS_WINDOWS_MOBILE# if (defined(_MSC_VER) || GTEST_OS_WINDOWS_MINGW) && !GTEST_OS_WINDOWS_MOBILE// Death test children can be terminated with _abort(). On Windows,// _abort() can show a dialog with a warning message. This forces the// abort message to go to stderr instead._set_error_mode(_OUT_TO_STDERR); # endif# if defined(_MSC_VER) && !GTEST_OS_WINDOWS_MOBILE// In the debug version, Visual Studio pops up a separate dialog// offering a choice to debug the aborted program. We need to suppress// this dialog or it will pop up for every EXPECT/ASSERT_DEATH statement// executed. Google Test will notify the user of any unexpected// failure via stderr.if (!GTEST_FLAG(break_on_failure))_set_abort_behavior(0x0, // Clear the following flags:_WRITE_ABORT_MSG | _CALL_REPORTFAULT); // pop-up window, core dump. # endif} #endif // GTEST_OS_WINDOWSreturn internal::HandleExceptionsInMethodIfSupported(impl(),&internal::UnitTestImpl::RunAllTests,"auxiliary test code (environments or event listeners)") ? 0 : 1; }internal::HandleExceptionsInMethodIfSupported() 是 Google test 定義的一個用于執行類的成員函數的函數,這里不再詳細分析這個函數的實現。UnitTest::Run() 函數實際上通過 googletest/googletest/src/gtest.cc 中定義的 internal::UnitTestImpl::RunAllTests() 函數執行所有的測試用例:
// Runs all tests in this UnitTest object, prints the result, and // returns true if all tests are successful. If any exception is // thrown during a test, the test is considered to be failed, but the // rest of the tests will still be run. // // When parameterized tests are enabled, it expands and registers // parameterized tests first in RegisterParameterizedTests(). // All other functions called from RunAllTests() may safely assume that // parameterized tests are ready to be counted and run. bool UnitTestImpl::RunAllTests() {// True iff Google Test is initialized before RUN_ALL_TESTS() is called.const bool gtest_is_initialized_before_run_all_tests = GTestIsInitialized();// Do not run any test if the --help flag was specified.if (g_help_flag)return true;// Repeats the call to the post-flag parsing initialization in case the// user didn't call InitGoogleTest.PostFlagParsingInit();// Even if sharding is not on, test runners may want to use the// GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding// protocol.internal::WriteToShardStatusFileIfNeeded();// True iff we are in a subprocess for running a thread-safe-style// death test.bool in_subprocess_for_death_test = false;#if GTEST_HAS_DEATH_TESTin_subprocess_for_death_test =(internal_run_death_test_flag_.get() != nullptr); # if defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_)if (in_subprocess_for_death_test) {GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_();} # endif // defined(GTEST_EXTRA_DEATH_TEST_CHILD_SETUP_) #endif // GTEST_HAS_DEATH_TESTconst bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,in_subprocess_for_death_test);// Compares the full test names with the filter to decide which// tests to run.const bool has_tests_to_run = FilterTests(should_shard? HONOR_SHARDING_PROTOCOL: IGNORE_SHARDING_PROTOCOL) > 0;// Lists the tests and exits if the --gtest_list_tests flag was specified.if (GTEST_FLAG(list_tests)) {// This must be called *after* FilterTests() has been called.ListTestsMatchingFilter();return true;}random_seed_ = GTEST_FLAG(shuffle) ?GetRandomSeedFromFlag(GTEST_FLAG(random_seed)) : 0;// True iff at least one test has failed.bool failed = false;TestEventListener* repeater = listeners()->repeater();start_timestamp_ = GetTimeInMillis();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(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++) {// We want to preserve failures generated by ad-hoc test// assertions executed before RUN_ALL_TESTS().ClearNonAdHocTestResult();const TimeInMillis start = GetTimeInMillis();// Shuffles test suites and tests if requested.if (has_tests_to_run && GTEST_FLAG(shuffle)) {random()->Reseed(static_cast<UInt32>(random_seed_));// This should be done before calling OnTestIterationStart(),// such that a test event listener can see the actual test order// in the event.ShuffleTests();}// 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.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);if (test_part_result.type() == TestPartResult::kSkip) {const std::string& result = test_part_result.message();printf("%s\n", result.c_str());}}fflush(stdout);} else if (!Test::HasFatalFailure()) {for (int test_index = 0; test_index < total_test_suite_count();test_index++) {GetMutableSuiteCase(test_index)->Run();}}// Tears down all environments in reverse order afterwards.repeater->OnEnvironmentsTearDownStart(*parent_);std::for_each(environments_.rbegin(), environments_.rend(),TearDownEnvironment);repeater->OnEnvironmentsTearDownEnd(*parent_);}elapsed_time_ = GetTimeInMillis() - start;// 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;}// Restores the original test order after the iteration. This// allows the user to quickly repro a failure that happens in the// N-th iteration without repeating the first (N - 1) iterations.// This is not enclosed in "if (GTEST_FLAG(shuffle)) { ... }", in// case the user somehow changes the value of the flag somewhere// (it's always safe to unshuffle the tests).UnshuffleTests();if (GTEST_FLAG(shuffle)) {// Picks a new random seed for each iteration.random_seed_ = GetNextRandomSeed(random_seed_);}}repeater->OnTestProgramEnd(*parent_);if (!gtest_is_initialized_before_run_all_tests) {ColoredPrintf(COLOR_RED,"\nIMPORTANT NOTICE - DO NOT IGNORE:\n""This test program did NOT call " GTEST_INIT_GOOGLE_TEST_NAME_"() before calling RUN_ALL_TESTS(). This is INVALID. Soon " GTEST_NAME_" will start to enforce the valid usage. ""Please fix it ASAP, or IT WILL START TO FAIL.\n"); // NOLINT #if GTEST_FOR_GOOGLE_ColoredPrintf(COLOR_RED,"For more details, see http://wiki/Main/ValidGUnitMain.\n"); #endif // GTEST_FOR_GOOGLE_}return !failed; }internal::UnitTestImpl::RunAllTests() 函數通過 internal::UnitTestImpl::GetMutableSuiteCase() 函數拿到測試套件 TestSuite 并執行其 Run() 函數:
void TestSuite::Run() {if (!should_run_) return;internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();impl->set_current_test_suite(this);TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();// Call both legacy and the new APIrepeater->OnTestSuiteStart(*this); // Legacy API is deprecated but still available #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPIrepeater->OnTestCaseStart(*this); #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPIimpl->os_stack_trace_getter()->UponLeavingGTest();internal::HandleExceptionsInMethodIfSupported(this, &TestSuite::RunSetUpTestSuite, "SetUpTestSuite()");start_timestamp_ = internal::GetTimeInMillis();for (int i = 0; i < total_test_count(); i++) {GetMutableTestInfo(i)->Run();}elapsed_time_ = internal::GetTimeInMillis() - start_timestamp_;impl->os_stack_trace_getter()->UponLeavingGTest();internal::HandleExceptionsInMethodIfSupported(this, &TestSuite::RunTearDownTestSuite, "TearDownTestSuite()");// Call both legacy and the new APIrepeater->OnTestSuiteEnd(*this); // Legacy API is deprecated but still available #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPIrepeater->OnTestCaseEnd(*this); #endif // GTEST_REMOVE_LEGACY_TEST_CASEAPIimpl->set_current_test_suite(nullptr); }TestSuite::Run() 函數通過 GetMutableTestInfo() 函數獲得 TestInfo 并執行其 Run() 函數,TestInfo::Run() 函數定義如下:
// Creates the test object, runs it, records its result, and then // deletes it. void TestInfo::Run() {if (!should_run_) return;// Tells UnitTest where to store test result.internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();impl->set_current_test_info(this);TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater();// Notifies the unit test event listeners that a test is about to start.repeater->OnTestStart(*this);const TimeInMillis start = internal::GetTimeInMillis();impl->os_stack_trace_getter()->UponLeavingGTest();// Creates the test object.Test* const test = internal::HandleExceptionsInMethodIfSupported(factory_, &internal::TestFactoryBase::CreateTest,"the test fixture's constructor");// Runs the test if the constructor didn't generate a fatal failure or invoke// GTEST_SKIP().// Note that the object will not be nullif (!Test::HasFatalFailure() && !Test::IsSkipped()) {// This doesn't throw as all user code that can throw are wrapped into// exception handling code.test->Run();}if (test != nullptr) {// Deletes the test object.impl->os_stack_trace_getter()->UponLeavingGTest();internal::HandleExceptionsInMethodIfSupported(test, &Test::DeleteSelf_, "the test fixture's destructor");}result_.set_start_timestamp(start);result_.set_elapsed_time(internal::GetTimeInMillis() - start);// Notifies the unit test event listener that a test has just finished.repeater->OnTestEnd(*this);// Tells UnitTest to stop associating assertion results to this// test.impl->set_current_test_info(nullptr); }TestInfo::Run() 函數創建測試用例類對象,并執行其 Run() 函數。Test::Run() 執行測試用例定義的 SetUp(),測試用例主體 TestBody() 函數,和 TearDown() 函數:
// Runs the test and updates the test result. void Test::Run() {if (!HasSameFixtureClass()) return;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()"); }測試用例的調用執行過程大概是這樣的:
RUN_ALL_TESTS() -> UnitTest::Run() -> UnitTestImpl::RunAllTests() -> TestSuite::Run() -> TestInfo::Run() -> Test::Run() -> Test::TestBody()。
Done。
總結
以上是生活随笔為你收集整理的Googletest 实现简要分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WebRTC Audio 接收和发送的关
- 下一篇: WebRTC 中的基本音频处理操作