IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 玩转C++单元测试之快速上手gtest -> 正文阅读

[开发测试]玩转C++单元测试之快速上手gtest

1.gtest简介

gtest是一个跨平台的(Liunx、Mac OS X、Windows、Cygwin、Windows CE and Symbian)C++单元测试框架,由google公司发布。gtest是为在不同平台上为编写C++测试而生成的,它提供了丰富的断言、致命和非致命判断、参数化、“死亡测试”等等。
gtest在github上的链接为:googletest

2.gtest原理

gtest主要由一系列的宏和事件实现。
“事件” 的本质是gtest框架提供了一个机会, 可以使用这样的机会来执行定制的代码, 来给测试用例准备/清理数据。

  1. 宏:有TESTTEST_F宏,TEST宏针对简单的测试用例,TEST_F宏针对需要做初始化和资源回收的测试用例,有点像类似C++的构造函数和析构函数,两个宏都是把参数展开后拼成一个类。
  2. 事件:分为三种事件
    1)TestSuite事件
    需要写一个类,继承testing::Test,然后实现两个静态方法:SetUpTestCase方法在第一个TestCase之前执行;TearDownTestCase方法在最后一个TestCase之后执行。
    2)TestCase事件
    是挂在每个用例执行前后的,需要实现的是SetUp方法和TearDown方法。SetUp方法在每个TestCase之前执行;TearDown方法在每个TestCase之后执行。下面是一个例子:
    在这里插入图片描述
    3)全局事件
    要实现全局事件,必须写一个类,继承testing::Environment类,实现里面的SetUp和TearDown方法。SetUp方法在所有测试用例执行前执行;TearDown方法在所有测试用例执行后执行。
    除了要继承testing::Environment类,还要定义一个该全局环境的一个对象并将该对象添加到全局测试环境中。
    全局事件可以按照下列方式来使用:
    在这里插入图片描述

3.gtest安装

3.1使用dnf进行安装

1.更新dnf源
sudo yum install epel-release
sudo yum install dnf
2.安装gtest
sudo dnf install dnf-plugins-core
sudo dnf install gtest gtest-devel
使用find查看gtest头文件位置:find /usr -name gtest.h显示如下即为安装成功。
在这里插入图片描述

3.2编译gtest项目源码

1.从github下载源码:git clone https://github.com/google/googletest.git
下载后内容如下:
在这里插入图片描述
可以看到里面既有gtest也有gmock。大部分情况下,gmock是配合gtest来做白盒测试的。注意编译该项目时,要求gcc版本在5.0以上,如果gcc版本低于5.0,请参考gcc4.9升级gcc10升级gcc。
在这里插入图片描述
2.创建build目录,在build目录下执行cmake ../ -DCMAKE_BUILD_TYPE=Release
在这里插入图片描述
3.编译安装 make && make install
在这里插入图片描述
在这里插入图片描述

4.gtest内置测试相关的宏

TEST(test_case_name, test_name)
多个测试场景需要相同数据配置的情况,用TEST_F。
//TEST_F test fixture,测试夹具,测试套,承担了一个注册的功能(为测试类的类名)。
TEST_F(test_fixture,test_name)
TEST_F宏的使用需要按照C++的风格定义类,这个类需要继承自testing::Test并且重写这四个成员函数:SetUpTestCase、TearDownTestCase、SetUp、TearDown。如果有多个测试用例,那么SetUpTestCase就会在所有用例之前执行,TearDownTestCase会在所有用例之后执行;SetUp会在单个用例之前执行,TearDown会在单个用例之后执行。
【注意】使用TEST宏时,test_case_name不要求是当前测试类的类名,而使用TEST_F宏时,第一个参数必须是当前测试类的类名。
在这里插入图片描述
TEST_F宏第一个参数不是当前测试类的类名时,编译错误:
在这里插入图片描述
TEST宏的作用是创建一个简单测试,它定义了一个测试函数,在这个函数里可以使用任何C++代码并使用提供的断言来进行检查。

5.gtest断言

gtest中断言的宏可以分为两类:一类是ASSERT宏,另一类是EXPECT宏。
1、ASSERT_系列:如果当前点检测失败则退出当前函数
2、EXPECT_系列:如果当前点检测失败则继续往下执行
如果对自动输出的错误信息不满意的话,也可以通过operator<<在失败的时候打印日志,将一些自定义的信息输出。
常用ASSERT_系列:

宏类型宏名称功能描述
bool值检查ASSERT_TRUE(条件)判断条件是否为true期待结果是true
bool值检查ASSERT_FALSE(条件)判断条件是否为false期待结果是false
数值型数据检查ASSERT_EQ(参数1,参数2)equal相等为true
数值型数据检查ASSERT_NE(参数1,参数2)not equal不等于返回true
数值型数据检查ASSERT_LT(参数1,参数2)less than小于返回true
数值型数据检查ASSERT_GT(参数1,参数2)greater than大于返回true
数值型数据检查ASSERT_LE(参数1,参数2)less equal小于等于返回true
数值型数据检查ASSERT_GE(参数1,参数2)greater equal大于等于返回true
数值型数据检查ASSERT_FLOAT_EQ(expected, actual)equal两个float值相同返回true
数值型数据检查ASSERT_DOUBLE_EQ(expected, actual)equal两个double值相同返回true
字符串检查ASSERT_STREQ(expected_str, actual_str)判断字符串是否相等两个C风格的字符串相等返回true
字符串检查ASSERT_STRNE(expected, actual)判断字符串不相等两个C风格的字符串不相等时返回true
字符串检查ASSERT_STRCASEEQ(expected_str, actual_str)判断字符串是否相等(忽略大小写)/
字符串检查ASSERT_STRCASENE(str1, str2)判断字符串不相等(忽略大小写)/

EXPECT_系列,具有ASSERT系列类似的宏结构。将上表中的ASSERT换成EXPECT即可。

6.自定义测试失败信息输出

在这里插入图片描述

7.gtest demo

7.1简单用法

下面的例子展示了gtest最简单的用法,直接引入gtest头文件和库文件即可。
在这里插入图片描述
在这里插入图片描述

7.2作为测试类使用

7.2.1定义一个要被测试的类

在这里插入图片描述

7.2.2定义测试类

把要测试的类作为测试类的成员变量,重写SetUpTestCase、TearDownTestCase、SetUp、TearDown成员函数。
在这里插入图片描述
实测SetUpTestCase、TearDownTestCase、SetUp、TearDown四个函数只用重写其中的一对即可(如SetUp和TearDown、SetUpTestCase和TearDownTestCase均可)。可以按实际需求选择要重写的函数。注意SetUpTestCase和TearDownTestCase是static函数,SetUp和TearDown是虚函数。gtest中函数声明如下:
在这里插入图片描述
重写任意一对即可:
在这里插入图片描述
在这里插入图片描述

7.3执行所有测试用例

在这里插入图片描述

8.gtest测试类的私有成员

使用gtest编写单元测试,一个最常见的问题是对类私有成员的测试与验证。理想情况下,我们希望在测试中,类中所有的数据与方法都是可以访问的;而在产品代码中,只暴露实现定义好的接口。
gtest官方文档中也提到了对私有成员的处理,方法有两种:一是使用friend关键字;二是重构采用Pimpl模式,公共类中只暴露接口,而实现类中暴露所有细节(public),测试时包含实现类即可。当然,还有另外一种简单暴力的方法,要达到的目的无非是在产品代码中,该pubic的是public,该private的还是private;而在测试代码中,全部都是public。加宏编译,将private/protected全部改为public。

8.1加宏编译

在测试类头文件中添加:
#ifdef GTEST_API_
#define private public
#define protected public
#endif
下面是一个测试private方法的例子:
在这里插入图片描述
如果直接测试,由于private方法无法被访问,编译失败
在这里插入图片描述
加入宏后,重新编译:
在这里插入图片描述
优点:可以非常方便的使用被测试类中的任何成员
缺点:一是使得访问私有成员过于容易,从而导致写出来的test访问私有成员的可能性增大。测试访问了私有成员,依赖于实现,这会让单元测试成为重构的负担,而不是保证。二是这种方法是不标准的C++用法: C++标准不允许重定义关键词,所以这种方法即使此时在当前的编译器上是可行的,也不能保证将来,或者在其他编译器上可行;public, protected private等访问修饰符可能会影响对象成员的布局,这样当测试是直接链接到产品代码时会有问题。
如果是以纯源代码的方式使用产品类的,这个方法没有任何问题;但如果是通过静态库,或者动态库的方式使用产品类的,在测试代码中若直接使用这些库,编译是没有问题,因为全部伪装成了public,但在链接的时候,因为private的成员是没有从库中导出来的,必然会出现链接错误。此时有两个方案:一是以GTEST的方式重新编译库;二是直接将产品源代码编译进你的测试工程中去。
所以,除非对以上利弊十分清楚并且可以接受,不然,还是使用官方的FRIEND_TEST要更好一些。

8.2 FRIEND_TEST

摘自官方文档:
Private class members are only accessible from within the class or by friends. To access a class’ private members, you can declare your test fixture as a friend to the class and define accessors in your fixture. Tests using the fixture can then access the private members of your production class via the accessors in the fixture. Note that even though your fixture is a friend to your production class, your tests are not automatically friends to it, as they are technically defined in sub-classes of the fixture.( 类的私有成员只能从类内部或友元函数访问。要访问类的私有成员,可以将测试夹具声明为类的友元,并在fixture中定义访问器。然后,使用fixture的测试可以通过fixture中的访问器访问生产类的私有成员。请注意,即使你的fixture是生产类的友元,你的测试也不会自动成为它的友元,因为它们是在fixture的子类中定义的。)
FRIEND_TEST(TestCaseName, TestName)
展开后如下:
#define FRIEND_TEST(test_case_name, test_name)
friend class test_case_name##_##test_name##_Test
gtest通过FRIEND_TEST(TestCaseName, TestName)声明友元类,即TestCaseName为友元类,而TestName为具体的case名。
要使用FRIEND_TEST,在被测试的类中添加:
FRIEND_TEST(TestCaseName, TestName),如
在这里插入图片描述
在测试类中包含被测试类的头文件,使用友元调用被测试类的private函数:
在这里插入图片描述
注意,对FRIEND_TEST声明的友元类测试时,当使用TEST宏,TEST宏的两个参数必须和FRIEND_TEST的宏参数保持一致。

在这里插入图片描述
或者,也可以使用TEST_F宏

在这里插入图片描述
上例中给了两种访问私有变量的方式:
一种是FRIEND_TEST(FriendTest, addTest)声明的类,然后通过TEST(FriendTest, addTest)实现测试特例实体,实体中需要使用FriendTest的构造函数构造一个对象,然后调用其私有的add方法。
一种是FRIEND_TEST(Friend_Test2, addTest)声明的类。它使用到了Test Fixtures技术。在Friend_Test2类中,声明了一个FriendTest对象。然后在TEST_F(Friend_Test2, addTest)中直接使用了Friend_Test2类中的成员变量调用add方法。TEST_F(Friend_Test2, addTest)既继承于Friend_Test2,又是FriendTest的友元类。
缺点:
需要通过FRIEND_TEST宏来新增该类的友元类(就是通过友元类来访问私有成员,所以这是一种侵入式的测试——修改了原来类的结构)。

8.3使用pimpl重构被测代码

Pimpl主要的作用是解开代码调用接口和具体实现的耦合,具体的实现可以参考C++程序设计机制——PIMPL机制。利用这种方式打开私有成员,思路是先对被测代码按照pimpl模式进行重构,把具体实现的私有成员全部放到另外一个辅助类,通过指针访问实现的私有成员,然后对这个辅助类进行原类的私有成员测试。
原被测类如下:
//MyClass.h

在这里插入图片描述
修改后的MyClass为:

在这里插入图片描述
通过辅助类进行测试:
在这里插入图片描述
经过上面的处理,调用新的MyClass类,就可以访问之前的私有成员了,pub_square ()对应原来的square (),pub_func ()对应原MyClass私有成员MyPrivateClass的func ()。也就可以通过调用新的MyClass来访问其原私有成员进行测试了。
缺点:实现比较复杂。如果采用此方法,需要开发编码时就采用该模式,或者提测后人工对代码进行重构,工作量比较大。
如果只是为了支持测试而做这样的重构,可能没有太大意义。况且,手工重构很麻烦。

9.gtest-demo git链接

以上截图代码示例使用git clone https://github.com/Angeliau/gtest-demo.git即可下载。demo使用Qt Creator生成,如果需要使用cmake,请自行生成CMakeLists.txt。

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-04-26 12:07:07  更:2022-04-26 12:07:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 2:50:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码