Google Test源码浅析(三) -------- RUN_ALL_TESTS

2023-10-12 15:30

本文主要是介绍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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/196764

相关文章

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

浅析CSS 中z - index属性的作用及在什么情况下会失效

《浅析CSS中z-index属性的作用及在什么情况下会失效》z-index属性用于控制元素的堆叠顺序,值越大,元素越显示在上层,它需要元素具有定位属性(如relative、absolute、fi... 目录1. z-index 属性的作用2. z-index 失效的情况2.1 元素没有定位属性2.2 元素处

Spring 中 BeanFactoryPostProcessor 的作用和示例源码分析

《Spring中BeanFactoryPostProcessor的作用和示例源码分析》Spring的BeanFactoryPostProcessor是容器初始化的扩展接口,允许在Bean实例化前... 目录一、概览1. 核心定位2. 核心功能详解3. 关键特性二、Spring 内置的 BeanFactory

浅析Python中的绝对导入与相对导入

《浅析Python中的绝对导入与相对导入》这篇文章主要为大家详细介绍了Python中的绝对导入与相对导入的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1 Imports快速介绍2 import语句的语法2.1 基本使用2.2 导入声明的样式3 绝对import和相对i

浅析如何使用Swagger生成带权限控制的API文档

《浅析如何使用Swagger生成带权限控制的API文档》当涉及到权限控制时,如何生成既安全又详细的API文档就成了一个关键问题,所以这篇文章小编就来和大家好好聊聊如何用Swagger来生成带有... 目录准备工作配置 Swagger权限控制给 API 加上权限注解查看文档注意事项在咱们的开发工作里,API

浅析Rust多线程中如何安全的使用变量

《浅析Rust多线程中如何安全的使用变量》这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下... 目录1. 向线程传递变量2. 多线程共享变量引用3. 多线程中修改变量4. 总结在Rust语言中,一个既引人入胜又可

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步

python subprocess.run中的具体使用

《pythonsubprocess.run中的具体使用》subprocess.run是Python3.5及以上版本中用于运行子进程的函数,它提供了更简单和更强大的方式来创建和管理子进程,本文就来详细... 目录一、详解1.1、基本用法1.2、参数详解1.3、返回值1.4、示例1.5、总结二、subproce