`
russelltao
  • 浏览: 157173 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

如何用googletest写单元测试

阅读更多

googletest是一个用来写C++单元测试的框架,它是跨平台的,可应用在windows、linux、Mac等OS平台上。下面,我来说明如何使用最新的1.6版本gtest写自己的单元测试。

本文包括以下几部分:1、获取并编译googletest(以下简称为gtest);2、如何编写单元测试用例;3、如何执行单元测试。4、google test内部是如何执行我们的单元测试用例的。


1. 获取并编译gtest

gtest试图跨平台,理论上,它就应该提供多个版本的binary包。但事实上,gtest只提供源码和相应平台的编译方式,这是为什么呢?google的解释是,我们在编译出gtest时,有些独特的工程很可能希望在编译时加许多flag,把编译的过程下放给用户,可以让用户更灵活的处理。这个仁者见仁吧,反正也是免费的BSD权限。


源码的获取地址:http://code.google.com/p/googletest/downloads/list


目前gtest提供的是1.6.0版本,我们看看与以往版本1.5.0的区别:

 

  1. Changes for 1.6.0:  
  2.   
  3. * New feature: ADD_FAILURE_AT() for reporting a test failure at the  
  4.   given source location -- useful for writing testing utilities.  
  5. 。。。 。。。  
  6. * Bug fixes and implementation clean-ups.  
  7. * Potentially incompatible changes: disables the harmful 'make install'  
  8.   command in autotools.  

 

就是最下面一行,make install禁用了,郁闷了吧?UNIX的习惯编译方法:./configure;make;make install失灵了,只能说google比较有种,又开始挑战用户习惯了。

那么怎么编译呢?

先进入gtest目录(解压gtest.zip包过程就不说了),执行以下两行命令:

 

  1. g++ -I./include -I./ -c ./src/gtest-all.cc  
  2. ar -rv libgtest.a gtest-all.o  

之后,生成了libgtest.a,这个就是我们要的东东了。以后写自己的单元测试,就需要libgtest.a和gtest目录下的include目录,所以,这1文件1目录我们需要拷贝到自己的工程中。

 

编译完成后怎么验证是否成功了呢?(相当不友好!)

 

  1. cd ${GTEST_DIR}/make  
  2.   make  
  3.   ./sample1_unittest  

如果看到:

 

 

  1. Running main() from gtest_main.cc  
  2. [==========] Running 6 tests from 2 test cases.  
  3. [----------] Global test environment set-up.  
  4. [----------] 3 tests from FactorialTest  
  5. [ RUN      ] FactorialTest.Negative  
  6. [       OK ] FactorialTest.Negative (0 ms)  
  7. [ RUN      ] FactorialTest.Zero  
  8. [       OK ] FactorialTest.Zero (0 ms)  
  9. [ RUN      ] FactorialTest.Positive  
  10. [       OK ] FactorialTest.Positive (0 ms)  
  11. [----------] 3 tests from FactorialTest (0 ms total)  
  12.   
  13. [----------] 3 tests from IsPrimeTest  
  14. [ RUN      ] IsPrimeTest.Negative  
  15. [       OK ] IsPrimeTest.Negative (0 ms)  
  16. [ RUN      ] IsPrimeTest.Trivial  
  17. [       OK ] IsPrimeTest.Trivial (0 ms)  
  18. [ RUN      ] IsPrimeTest.Positive  
  19. [       OK ] IsPrimeTest.Positive (0 ms)  
  20. [----------] 3 tests from IsPrimeTest (0 ms total)  
  21.   
  22. [----------] Global test environment tear-down  
  23. [==========] 6 tests from 2 test cases ran. (0 ms total)  
  24. [  PASSED  ] 6 tests.  

那么证明编译成功了。

 


2、如何编写单元测试用例

以一个例子来说。我写了一个开地址的哈希表,它有del/get/add三个主要方法需要测试。在测试的时候,很自然,我只希望构造一个哈希表对象,对之做许多种不同组合的操作,以验证三个方法是否正常。所以,gtest提供的TEST方式我不会用,因为多个TEST不能共享同一份数据,而且还有初始化哈希表对象的过程呢。所以我用TEST_F方式。



上面是我要执行单元测试的类图。那么,我需要写一系列单元测试用例来测试这个类。用gtest,首先要声明一个类,继承自gtest里的Test类:



代码很简单:

 

  1. class CHashTableTest : public ::testing::Test {  
  2. protected:  
  3.     CHashTableTest():ht(100){  
  4.   
  5.     }  
  6.     virtual void SetUp() {  
  7.         key1 = "testkey1";  
  8.         key2 = "testkey2";  
  9.     }  
  10.   
  11.     // virtual void TearDown() {}  
  12.     CHashTable ht;  
  13.   
  14.     string key1;  
  15.     string key2;  
  16. };  


 

然后开始写测试用例,用例里可以直接使用上面类中的成员。



  1. TEST_F(CHashTableTest, hashfunc)  
  2. {  
  3.     CHashElement he;  
  4.   
  5.     ASSERT_NE(\  
  6.             ht.getHashKey((char*)key1.c_str(), key1.size(), 0),\  
  7.             ht.getHashKey((char*)key2.c_str(), key2.size(), 0));  
  8.   
  9.     ASSERT_NE(\  
  10.             ht.getHashKey((char*)key1.c_str(), key1.size(), 0),\  
  11.             ht.getHashKey((char*)key1.c_str(), key1.size(), 1));  
  12.   
  13.     ASSERT_EQ(\  
  14.             ht.getHashKey((char*)key1.c_str(), key1.size(), 0),\  
  15.             ht.getHashKey((char*)key1.c_str(), key1.size(), 0));  
  16. }  

注意,TEST_F宏会直接生成一个类,这个类继承自上面我们写的CHashTableTest类。

 

gtest提供ASSERT_和EXPECT_系列的宏,用于判断二进制、字符串等对象是否相等、真假等等。这两种宏的区别是,ASSERT_失败了不会往下执行,而EXPECT_会继续。


3、如何执行单元测试

首先,我们自己要有一个main函数,函数内容非常简单:

 

  1. #include "gtest/gtest.h"  
  2.   
  3. int main(int argc, char** argv) {  
  4.     testing::InitGoogleTest(&argc, argv);  
  5.   
  6.     // Runs all tests using Google Test.  
  7.     return RUN_ALL_TESTS();  
  8. }  

InitGoogleTest会解析参数。RUN_ALL_TESTS会把整个工程里的TEST和TEST_F这些函数全部作为测试用例执行一遍。

 


执行时,假设我们编译出的可执行文件叫unittest,那么直接执行./unittest就会输出结果到屏幕,例如:

 

  1. [==========] Running 4 tests from 1 test case.  
  2. [----------] Global test environment set-up.  
  3. [----------] 4 tests from CHashTableTest  
  4. [ RUN      ] CHashTableTest.hashfunc  
  5. [       OK ] CHashTableTest.hashfunc (0 ms)  
  6. [ RUN      ] CHashTableTest.addget  
  7. [       OK ] CHashTableTest.addget (0 ms)  
  8. [ RUN      ] CHashTableTest.add2get  
  9. testCHashTable.cpp:79: Failure  
  10. Value of: getHe->m_pNext==NULL  
  11.   Actual: true  
  12. Expected: false  
  13. [  FAILED  ] CHashTableTest.add2get (1 ms)  
  14. [ RUN      ] CHashTableTest.delget  
  15. [       OK ] CHashTableTest.delget (0 ms)  
  16. [----------] 4 tests from CHashTableTest (1 ms total)  
  17.   
  18. [----------] Global test environment tear-down  
  19. [==========] 4 tests from 1 test case ran. (1 ms total)  
  20. [  PASSED  ] 3 tests.  
  21. [  FAILED  ] 1 test, listed below:  
  22. [  FAILED  ] CHashTableTest.add2get  

 

  1. </pre><p>可以看到,对于错误的CASE,会标出所在文件及其行数。</p><p></p>如果我们需要输出到XML文件,则执行./unittest --gtest_output=xml,那么会在当前目录下生成test_detail.xml 文件,内容如下:<p></p><p></p><pre name="code" class="cpp"><?xml version="1.0" encoding="UTF-8"?>  
  2. <testsuites tests="3" failures="0" disabled="0" errors="0" time="0.001" name="AllTests">  
  3.   <testsuite name="CHashTableTest" tests="3" failures="0" disabled="0" errors="0" time="0.001">  
  4.     <testcase name="hashfunc" status="run" time="0.001" classname="CHashTableTest" />  
  5.     <testcase name="addget" status="run" time="0" classname="CHashTableTest" />  
  6.     <testcase name="delget" status="run" time="0" classname="CHashTableTest" />  
  7.   </testsuite>  
  8. </testsuites>  

如此,一个简单的单元测试写完。因为太简单,所以不需要使用google mock模拟一些依赖。后续我再写结合google mock来写一些复杂的gtest单元测试。

下面来简单说下gtest的工作流程。


4、google test内部是如何执行我们的单元测试用例的

首先从main函数看起。

我们的main函数执行了RUN_ALL_TESTS宏,这个宏干了些什么事呢?

 

  1. #define RUN_ALL_TESTS()\  
  2.   (::testing::UnitTest::GetInstance()->Run())  
  3.   
  4. }  // namespace testing  

原来是调用了UnitTest静态工厂实例的Run方法!在gtest里,一切测试用例都是Test类的实例!所以,Run方法将会执行所有的Test实例来运行所有的单元测试,看看类图:

 


为什么说一切单元测试用例都是Test类的实例呢?

我们有两种写测试用例的方法,一种就是上面我说的TEST_F宏,这要求我们要显示的定义一个子类继承自Test类。在TEST_F宏里,会再次定义一个新类,继承自我们上面定义的子类(两重继承哈)。

第二种就是TEST宏,这个宏里不要求用户代码定义类,但在google test里,TEST宏还是定义了一个子类继承自Test类。

所以,UnitTest的Run方法只需要执行所有Test实例即可。


每个单元测试用例就是一个Test类子类的实例。它同时与TestResult,TestCase,TestInfo关联起来,用于提供结果。

当然,还有EventListen类来监控结果的输出,控制测试的进度等。


以上并没有深入细节,只是大致帮助大家理解,我们写的几个简单的gtest宏,和单元测试用例,到底是如何被执行的。接下来,我会通过gmock来深入的看看google单元测试的玩法。

分享到:
评论

相关推荐

    玩转Google开源C++单元测试框架Google Test系列.pdf

    Google Test(gtest)是由Google提供的一个C++单元测试框架,广泛应用于C++程序的测试中。本系列文档将详细介绍如何使用gtest,包括其下载、安装、配置以及编写测试案例。文档分为多个部分,涵盖了gtest的基本使用...

    google test 单元测试框架

    谷歌的gtest单元测试框架是一个广泛使用的开源工具,尤其在跨平台的软件开发中扮演着重要角色。这个框架为C++编程语言提供了强大的测试能力,帮助开发者确保代码的正确性和可靠性。gtest的核心理念是通过定义断言...

    Google开源C++单元测试框架Google Test教程 第1章

    Google开源C++单元测试框架Google Test教程 第1章 Google开源C++单元测试框架Google Test教程 第1章 【资源说明】 1、该资源介绍Google开源C++单元测试框架Google Test教程 第一章。 2、第一章的主要内容为:GTest...

    Linux下使用C++编写的并发服务器,redis缓存和MySQL数据库,GoogleTest单元测试和webbench压力测试

    spark一个Linux下使用C++学习编写的并发服务器,使用redis作为缓存和MySQL作为数据库,并利用GoogleTest编写单元测试和webbench进行压力测试。.zipspark一个Linux下使用C++学习编写的并发服务器,使用redis作为缓存...

    C++ 基础教程 - 如何使用google test进行单元测试 - googletest-vc17

    windows10 + vs 2022 构建的google test的静态库

    玩转Google开源C++单元测试框架GoogleTest.pdf

    玩转Google开源C++单元测试框架GoogleTest

    Qt使用Google Test项目

    总结来说,"Qt使用Google Test项目"旨在教给开发者如何在Qt环境中有效地利用Google Test进行单元测试,提升代码质量和可维护性。通过学习和实践,开发者能够编写出结构清晰、易于维护的测试代码,确保Qt应用程序的...

    玩转Google开源C++单元测试框架Google Test系列 gtest

    玩转Google开源C++单元测试框架Google Test系列 gtest

    GoogleTest测试C++框架

    GoogleTest是一款由Google开发的开源C++测试框架,它为C++程序员提供了编写单元测试的便利工具。GoogleTest的主要目标是简化和标准化C++代码的测试过程,确保代码的质量和可靠性。在本文中,我们将探讨如何在Windows...

    Google的开源C++单元测试框架Google Test使用教程

    前段时间学习和了解了下Google的开源C++单元测试框架Google Test,简称gtest,非常的不错。 我们原来使用的是自己实现的一套单元测试框架,在使用过程中,发现越来越多使用不便之处,而这样不便之处,gtest恰恰很好...

    GoogleTest谷歌C++测试框架

    Googletest 基于 xUnit 测试框架,这是一种流行的单元测试架构 测试发现: Googletest 会自动发现并运行您的测试,无需 手动注册测试 丰富的断言集: Googletest 提供了多种断言,例如相等、不平等、 异常等,使测试...

    C++ 基础教程 - 如何使用google test进行单元测试

    google test demo

    google test框架使用中文文档

    Google Test是Google开发的一款强大的C++测试框架,它使得C++开发者能够编写单元测试和集成测试,以确保代码的质量和稳定性。本文档将详细介绍Google Test框架的使用方法,包括基本概念、断言、测试套件、测试用例、...

    基于C++的Google Test单元测试框架设计源码

    本项目是基于C++的Google Test单元测试框架设计源码,包含235个文件,其中包括101个C++源文件、47个头文件、30个Python脚本、29个Markdown文档、6个.in文件、5个TXT文件、3个YAML文件、3个Bazel文件和2个SCSS文件。...

    googletest最新版本

    在"googletest-master"这个压缩包中,我们可以预期找到Google Test的源代码、头文件、构建脚本和可能的示例代码。开发者可以将这些源代码集成到自己的项目中,以便利用gtest进行单元测试。 以下是一些Google Test的...

Global site tag (gtag.js) - Google Analytics