C++单元测试之gtest&gmock这篇文章介绍C++单元测试工具gtestgmock,以及自己在前段时间做

单元测试不但可以增加开发者对于所完成代码的自信,同时,好的单元测试用例往往可以在回归测试的过程中,很好地保证之前所发生的修改没有破坏已有的程序逻辑。因此,单元测试不但不会成为开发者的负担,反而可以在保证开发质量的情况下,加速迭代开发的过程。

C++的单元测试框架,我见过最常多的就是gtest了。除此之外,boost也提供了一个用于单元测试的框架,boost仅在学校时使用过,印象中与gtest使用方式大同小异。

单元测试框架通常会对一些变量或函数设置期望,若变量值或返回值符合预期,就认为单元测试用例通过。gtest也提供了下面一些断言:

ASSERT_*系列的断言,当检查点失败时,立即退出单元测试;EXPECT_*系列的断言,当检查点失败时,单元测试还是会继续执行,但结束后会标记所有ECPECT_*失败的用例;EXPECT_CALL设置函数调用之后期望的实现,比如直接返回某一个值。该断言后面没有.Times()时,无论函数有没有调用都不会导致失败,如果有.Times()时,不满足.Times()设置的次数时就会导致期望失败;

有时候对于一些接口,比如向服务器发送请求。但单元测试中有没有可用于测试的服务器,这个时候就需要mock这个请求接口。mock工具的作用是指定函数的行为(模拟函数的行为)。可以对入参进行校验,对出参进行设定,还可以指定函数的返回值。

Mock的基本使用方法是:

因为Mock是基于多态实现的,gmock是不支持Mock全局函数或者静态成员函数的。对于这些全局函数,比较传统的做法是创建一个Wrapper,用虚方法对这些静态函数进行包裹.在测试的时候对Wrapper进行Mock便可控制被包裹的静态函数的行为。

单元测试的case不应该有直接的依赖关系,每一个case在SetUp之后应该达到可以直接测试的条件,在TearDown之后不应该残留任何状态。这里所说的[测试具有依赖关系的case]指的是:一个case测试的条件是另一个case执行正常路径之后的状态。说的有点绕,举个例子:

对于这三个case,测试的时候代码该怎么写呢?难道测case2的时候要把case1的正常路径写到case2的开头?测case3的时候要把case1和case2的正常路径写到case3的开头?这代码得有多臃肿?如果还有case4、case5呢?

对于这种情况,应该充分利用SetUp和TearDown。我会这样写:

TEST_F(AuthenticateTestauthen_success){authenticate_success();}TEST_F(AuthenticateTest,authen_failed){//错误case。这个就没必要封装函数了,因为其他地方也不会用到这个case}添加商品到购物车测试头文件:AddTest.h

classAddTest:publicAuthenticateTest//注意:这里要继承AuthenticateTest,而不是Test,因为AuthenticateTest类中有我们测试添加商品的条件:成功登陆{public:virtualvoidSetUp(){AuthenticateTest::SetUp();authenticate_success();//成功登陆//其他前提条件}virtualvoidTearDown(){//清理环境AuthenticateTest::TearDown();//父类的清理函数}protected:voidadd_success(){//正常case,可以使用EXPECT_*等条件}//如果接下来的case需要一些公共变量};添加商品到购物车测试源文件:AddTest.cpp

TEST_F(AddTestadd_success){add_success();}TEST_F(AddTest,add_failed){//错误case。这个就没必要封装函数了,因为其他地方也不会用到这个case}结账测试头文件:PayTest.h

classPayTest:publicAddTest//注意:这里要继承AddTest,而不是Test,因为AddTest类中有我们测试添加商品的条件:成功添加商品到购物车{public:virtualvoidSetUp(){AddTest::SetUp();add_success();//成功添加商品//其他前提条件}virtualvoidTearDown(){//清理环境AddTest::TearDown();//父类的清理函数}};结账测试源文件:PayTest.cpp

TEST_F(PayTestpay_success){}TEST_F(PayTest,pay_failed){}(3)依赖注入假如Mock类已经写好,那如何把实例化出来的Mock对象传入被测方法呢?(有时候被Mock的类或对象可能在被测接口内部使用)举个例子:需要Mock的类:

classMT{public:virtualvoidconnectDB(){//一些还未实现的,或不好用于测试的操作。比如访问数据库}};被Mock的对象处于被测类内部

classWrapper{public:virtualvoidinit()//如果init方法不是virtual,为了单元测试也要加上virtual。为什么要virtual,下文说{_mt=newMT;//难测点:待Mock类处于函数内,无法通过参数传入//dosomething}virtualvoidtoBeTestFunc()//被测对象{_mt->func();//otheroperator}private:MT*_mt;};Mock:

classMockMT:publicMT{public:MOCK_METHOD0(connectDB,void());}很关键的依赖注入部分,对待测类也进行Mock:

classMockWrapper:publicWrapper//依然需要Mock{public:MOCK_METHOD0(init,void());//这里就是为什么Wrapper::init是virtual的原因,需要MockvoidrealToBeTestFunc()//定义一个函数,但是调用父类的接口,原因在单元测试case中说{Wrapper::toBeTestFunc();}};

THE END
1.gtestNOTE: If you want to build an executable against gtest, but not declare it to be a test on its own (e.g., when you intend the executable to be run by rostest), use catkin_add_executable_with_gtest(). NOTE:Using Ubuntu 11.10 you will get a "undefined reference to `pthread_getspe...http://wiki.ros.org/gtest
2.macportspackagesgtest安装包下载开源镜像站macports-packages-gtest安装包是阿里云官方提供的开源镜像免费下载服务,每天下载量过亿,阿里巴巴开源镜像站为包含macports-packages-gtest安装包的几百个操作系统镜像和依赖包镜像进行免费CDN加速,更新频率高、稳定安全。https://mirrors.aliyun.com/macports/packages/gtest/
3.C++单元测试框架(gtest).PDFC++单元测试框架(gtest).PDF,原创:/coderzh/ 整理: 玩转 Google 开源 C++单元测试框架 Google Test 系列(gtest)之一 - 初识 gtest 玩转 Google 开源 C++单元测试框架 Google Test 系列(gtest)之一 - 初识 gtest 玩玩转转GGooooggllee开开源源 CC++++单单元元测测试试框https://max.book118.com/html/2018/0124/150350830.shtm
1.googletest(gtest)/googlemock(gmock)GTest Runneris a Qt5 based automated test-runner and Graphical User Interface with powerful features for Windows and Linux platforms. GoogleTest UIis a test runner that runs your test binary, allows you to track its progress via a progress bar, and displays a list of test failures. Clicking...https://github.com/google/googletest
2.gtest单元测试论算法工程师如何维护自己的代码这样会造成算法开发人员耗费大量的时间和精力。而gtest就是这样的一个工具,它是Google的一个开源框架,主要功能是用于编写单元测试,从而检查自己的程序是否符合预期行为。这当然是QA(测试工程师)最常用的工具,但是作为一名算法工程师也需要清楚自己的算法是否符合设计需求以及规范。https://blog.csdn.net/lovely_yoshino/article/details/124324445
3.gtest框架版本幸福的地图的技术博客单元测试不必从头开始,目前已经有很多优秀的测试框架可供选择。本文主要介绍google的gtest框架,其github地址:https://github.com/google/googletest gtest安装 从github的release中下载发布版本,目前最新版本为v1.10.0。以在windows下安装为例,Linux下类似。 https://blog.51cto.com/u_14112/12682391
4.GTest问题itest.nz腾讯云开发者社区添加以下代码,注意==不要包含gtest/gtest.h头文件==,若多包含可能会出现struct std::__cxx11::basic_stringbuf<_CharT, _Traits, _Alloc>::__xfer_bufptrs' redeclared with different access错误 代码语言:javascript 复制 #defineprivatepublic#defineprotectedpublic#undefprivate#undefprotected ...https://cloud.tencent.com/developer/article/2157972
5.FindGTest—CMake3.31.0DocumentationThe Google Testgtestlibrary, if found; adds Thread::Thread automatically GTest::gtest_main The Google Testgtest_mainlibrary, if found Added in version 3.23. GTest::gmock The Google Mockgmocklibrary, if found; adds Thread::Thread automatically ...https://cmake.org/cmake/help/latest/module/FindGTest.html
6.GTest的安装与使用【注】在GTest的安装与使用(https://www.cnblogs.com/helloworldcode/p/9606838.html) 的基础上进行了小部分修改补充 下载gtest,release-1.8.0 git clone https://github.com/google/googletest gtest编译 cd googletest 生成Makefile文件(先安装cmake,ubuntu系统:apt install cmake, windows系统:下载cmake-3.18....https://www.jianshu.com/p/96158afbb91d
7.unittestingI'm currently trying to implement the most basic test, to confirm I've compiled/installed gtest right and it's not working. The only source file (testgtest.cpp) is taken almost exactly fromthisprevious answer: #include <iostream> #include "gtest/gtest.h" ...https://stackoverflow.com/questions/8507723/how-to-start-working-with-gtest-and-cmake
8.ubuntu下gtest的调试技巧与常见问题解决云计算设置断点:在需要调试的地方使用断点,可以通过在代码中插入GTEST_BREAK()或者GTEST_BREAK_ON_FAILURE()来设置断点。 使用GDB调试:在运行测试时加上--gtest_break_on_failure参数,可以让GTest在断言失败时调用GDB。 打印调试信息:使用ADD_FAILURE()或ADD_FAILURE_AT()函数在测试中打印调试信息。 https://www.jindouyun.cn/document/cloud/details/341390
9.单元测试框架gtest使用研究gtest是一款由google开发并开源的C++单元测试框架,对C++的各种单元测试场景提供了完备的支持,并且可以在多种平台下运行,本文主要介绍gtest框架中测试部分的内容(mock部分将在下一篇中介绍)。gtest在Github地址为:GitHub - google/googletest: Googletest - Google Testing and Mocking Framework ...https://wsa.jianshu.io/p/8e858e64d359
10.C++使用gtest框架编写单元测试的教程详解C语言gtest 是 Google 开发的一个用于 C++ 的测试框架,广泛应用于编写和运行单元测试,并且支持任何类型的测试,而不仅仅是单元测试。 注意: 本教程使用 cmake 启动并运行 GoogleTest:需提前安装 CMake。 术语:测试(Test)、测试用例(Test Case)和测试套件(Test Suite)。 使用cmake 启动并运行 gtest 1. 设置项目 CMak...https://www.jb51.net/program/325466el1.htm
11.用於HAL測試的參數化GTestAndroidOpenSourceProjectHAL 介面可能會有多種實作方式。如要測試 HAL 實作的每個例項,標準做法是編寫值參數化 GTest。 基本測試設定 GTest 必須繼承基礎類別testing::TestWithParam,其中參數是每個例項的名稱。在SetUp方法中,您可以根據執行個體名稱例項化服務,如以下程式碼片段所示。 https://source.android.google.cn/docs/core/tests/vts/gtest?hl=zh-tw
12.googletestLinux环境安装使用1、准备测试框架gtest1.gtest源码下载:https://github.com/google/googletest2.使用CMake编译出静态库 libgtest.a 步骤: 1...mingw32-make 执行makefile文件编译gtest源码,生成libgtest.a 在新建build目录下,cmd进入命令行终端,执行mingw32-cmake。 2、搭建gtest工程 配置库路径 ...https://www.pianshen.com/article/1893984308/
13.电子邮件中国地质大学邮箱客户端设置指南:本指南以邮件账号cugtest@cug.edu.cn为例。 3、使用Pop协议与使用IMAP协议设置客户端有何区别? 简单地说,使用Pop协议的情况下,客户端只能将"收件箱"里的邮件收取到本地,并且在客户端上对本地邮件的操作均不会影响服务器上的邮件; ...https://wlzx.cug.edu.cn/xxhen/old/fw/dzyj.htm