本文主要是介绍Google Test源码浅析(三) -------- RUN_ALL_TESTS,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
-
-
- 一、例子引入:
- 二、源码分析
- 2.1 UnitTest::Run()
- 2.2 UnitTestImpl::RunAllTests()
- 2.4 TestCase::Run()
- 2.3 TestInfo::Run()
- 三、总结
-
一、例子引入:
TEST(TestCaseName1, TestName1){ cout << "hello1" << endl; } int main(int argc,char* argv[]) { testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }
分析:上述例子当中,看到RUN_ALL_TESTS()这个宏,从名字上来看,这是运行所有的测试用例,这才是我们运行测试用例的真正入口,下面来看一下具体的源码实现
二、源码分析
RUN_ALL_TESTS()之前是一个宏,将其实现为函数,在这里,调用了UnitTest单例的Run函数
int RUN_ALL_TESTS() GTEST_MUST_USE_RESULT_;
inline int RUN_ALL_TESTS() { return ::testing::UnitTest::GetInstance()->Run();
}
接着去看调用过程,可以看到,依次调用的过程是:
1. UnitTest::Run()
2. UnitTestImpl::RunAllTests()
3. TestCase::Run()
4. TestInfo::Run()
5. Test::Run()
2.1 UnitTest::Run()
int UnitTest::Run() { //关于死亡测试 const bool in_death_test_child_process = internal::GTEST_FLAG(internal_run_death_test).length() > 0; const internal::ScopedPrematureExitFile premature_exit_file( in_death_test_child_process ? NULL :internal::posix::GetEnv("TEST_PREMATURE_EXIT_FILE")); impl()->set_catch_exceptions(GTEST_FLAG(catch_exceptions)); //捕获异常 #if GTEST_HAS_SEH if (impl()->catch_exceptions() || in_death_test_child_process) { # if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT 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 _set_error_mode(_OUT_TO_STDERR); # endif # if _MSC_VER >= 1400 && !GTEST_OS_WINDOWS_MOBILE 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_HAS_SEH //以上全是关于死亡测试和跨平台异常的的一些设定,下面才是真正实现其功能的地方 return internal::HandleExceptionsInMethodIfSupported( impl(), &internal::UnitTestImpl::RunAllTests, "auxiliary test code (environments or event listeners)") ? 0 : 1; }
如果不涉及源码中的死亡测试以及跨平台可能出现异常的一些问题,其简化为
int UnitTest::Run()
{return internal::HandleExceptionsInMethodIfSupported( impl(), &internal::UnitTestImpl::RunAllTests, "auxiliary test code (environments or event listeners)") ? 0 : 1;
}
在将其简化,可以发现由impl对象指针调用了RunAllTests();
int UnitTest::Run()
{return impl->RunAllTests();
}
这里使用了impl()方法,该方法返回了一个UnitTestImpl对象指针impl_,由指针调用了RunAllTest,
UnitTest::UnitTest() { impl_ = new internal::UnitTestImpl(this); }
2.2 UnitTestImpl::RunAllTests()
源码:
bool UnitTestImpl::RunAllTests() { //准备工作 // Makes sure InitGoogleTest() was called. if (!GTestIsInitialized()) { printf("%s", "\nThis test program did NOT call ::testing::InitGoogleTest " "before calling RUN_ALL_TESTS(). Please fix it.\n"); return false; } // Do not run any test if the --help flag was specified. if (g_help_flag) return true; //重复对后标记解析初始化的调用,以防万一用户没有调用InitGoogleTest。 PostFlagParsingInit(); //关于对用户提供的设计 internal::WriteToShardStatusFileIfNeeded(); //对死亡测试线程安全方面的检测 bool in_subprocess_for_death_test = false; #if GTEST_HAS_DEATH_TEST in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL); # 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_TEST //与环境相关的设置,暂时不关心 const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex, in_subprocess_for_death_test); // 匹配测试用例,对所有的测试用例进行匹配,决定要执行哪一个测试用例 const bool has_tests_to_run = FilterTests(should_shard ? HONOR_SHARDING_PROTOCOL : IGNORE_SHARDING_PROTOCOL) > 0; //如果指定了gtestlisttest标志,则列出测试和出口。 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(); //上报事件OnTestProgramStart start_timestamp_ = GetTimeInMillis(); repeater->OnTestProgramStart(*parent_); const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat); const bool forever = repeat < 0; for (int i = 0; forever || i != repeat; i++) { //清除所有非AddHoc的测试结果,为后续运行做准备。 ClearNonAdHocTestResult(); const TimeInMillis start = GetTimeInMillis(); if (has_tests_to_run && GTEST_FLAG(shuffle)) { random()->Reseed(random_seed_); ShuffleTests(); } repeater->OnTestIterationStart(*parent_, i); if (has_tests_to_run) { repeater->OnEnvironmentsSetUpStart(*parent_); ForEach(environments_, SetUpEnvironment); repeater->OnEnvironmentsSetUpEnd(*parent_); if (!Test::HasFatalFailure()) { //核心代码 for (int test_index = 0; test_index < total_test_case_count(); test_index++) { GetMutableTestCase(test_index)->Run(); //逐个运行测试用例,执行后面的TestBody() } } repeater->OnEnvironmentsTearDownStart(*parent_); std::for_each(environments_.rbegin(), environments_.rend(), TearDownEnvironment); repeater->OnEnvironmentsTearDownEnd(*parent_); } elapsed_time_ = GetTimeInMillis() - start; repeater->OnTestIterationEnd(*parent_, i); if (!Passed()) { failed = true; } UnshuffleTests(); if (GTEST_FLAG(shuffle)) { // Picks a new random seed for each iteration. random_seed_ = GetNextRandomSeed(random_seed_); } } repeater->OnTestProgramEnd(*parent_); return !failed; }
上述源码中,提取出最核心的代码,如下:
for (int test_index = 0; test_index < total_test_case_count(); test_index++) { GetMutableTestCase(test_index)->Run(); //逐个运行测试用例,执行后面的TestBody() }
分析:上一篇看TEST宏的源码中,我们看到所有的测试用例都存放在一个数组当中,这里就利用这一特点,通过返回UnitTestImpl对象成员变量test_cases_中的元素——各个测试用例对象指针,然后调用测试用例的Run方法。
std::vector<TestCase*> test_cases_;
2.4 TestCase::Run()
void TestCase::Run() { if (!should_run_) return; internal::UnitTestImpl* const impl = internal::GetUnitTestImpl(); impl->set_current_test_case(this); TestEventListener* repeater = UnitTest::GetInstance()->listeners().repeater(); repeater->OnTestCaseStart(*this); impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported( this, &TestCase::RunSetUpTestCase, "SetUpTestCase()"); const internal::TimeInMillis start = internal::GetTimeInMillis(); //核心代码 for (int i = 0; i < total_test_count(); i++) { GetMutableTestInfo(i)->Run(); } elapsed_time_ = internal::GetTimeInMillis() - start; impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported(this, &TestCase::RunTearDownTestCase, "TearDownTestCase()"); repeater->OnTestCaseEnd(*this); impl->set_current_test_case(NULL); }
分析:和上面 UnitTestImpl::RunAllTests思想类似,其中核心的源码如下,这里还是获取特例信息,调用Run方法
for (int i = 0; i < total_test_count(); i++) { GetMutableTestInfo(i)->Run(); }
2.3 TestInfo::Run()
源码:
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(); 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"); if ((test != NULL) && !Test::HasFatalFailure()) { test->Run(); } // Deletes the test object. impl->os_stack_trace_getter()->UponLeavingGTest(); internal::HandleExceptionsInMethodIfSupported( test, &Test::DeleteSelf_, "the test fixture's destructor"); 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(NULL); }
核心源码分析:
Test* const test = internal::HandleExceptionsInMethodIfSupported( factory_, &internal::TestFactoryBase::CreateTest, "the test fixture's constructor"); if ((test != NULL) && !Test::HasFatalFailure()) { test->Run(); }
这里是创造一个对象:将工厂类对象指针调用的Create Test方法传入构造函数,new出一个TEST宏的一个类对象的指针,用这个对象指针去调用父类的Run方法,从而去调用TestBody方法(注:TestBody是上一篇中提到的TEST当中的虚函数)
三、总结
上面已经将调用过程所有的源码看完,下面来梳理一下这个过程:
这篇关于Google Test源码浅析(三) -------- RUN_ALL_TESTS的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!