玩转单元测试之gtest
引言
程序开发的时候,往往需要编写一些测试样例来完成功能测试,以保证自己的代码在功能上符合预期,能考虑到一些异常边界问题等等。
gtest快速入门
1.引入gtest
# 使用的是1.10版本,其他版本可根据需要选择
git clone -b v1.10.x https://github.com/google/googletest.git
cd googletest
mkdir build && cd build
cmake .. && make -j4
sudo make install
sudo ldconfig
2.编写第一个单测
2.1 待测试文件
#ifndef __HELLO_H__
#define __HELLO_H__#include <iostream>
#include <string>class Animal {
public:Animal(std::string name) : _name(name){}virtual ~Animal() {}virtual bool eat(const std::string& food) = 0;private:std::string _name;
};class Tigger : public Animal {
public:Tigger() : Animal("tigger"){}bool eat(const std::string& food) override{if (food == "meat") {return true;}return false;}
};class Horse : public Animal {
public:Horse() : Animal("Horse"){}bool eat(const std::string& food) override{if (food == "grass") {return true;}return false;}
};
#endif
2.2 单测文件
#include "hello.h"
#include "gtest/gtest.h"using namespace ::testing;namespace {
TEST(TestTigger, CaseEat)
{Animal *tigger = new Tigger();bool ret = tigger->eat("meat");EXPECT_TRUE(ret);ret = tigger->eat("grass");EXPECT_FALSE(ret);delete tigger;
}TEST(TestHorse, CaseEat)
{Animal *horse = new Horse();bool ret = horse->eat("grass");EXPECT_TRUE(ret);ret = horse->eat("meat");EXPECT_FALSE(ret);delete horse;
}
}
2.3 makefile文件
CXX = g++
CXXFLAGS = -Wall
LIBES = -lgtest -lgtest_main -lpthread
LPATH = -L/tools/googletest/1.11.0/build/lib # 替换成自己lib路径
HPATH = -I/tools/googletest/1.11.0/googletest/include/ # 替换成自己的include路径UTEST_OBJD = hello_unit_testhello_unit_test:hello_unit_test.cpp${CXX} -o $@ $+ -I ../ ${HPATH} ${CXXFLAGS} ${LIBES} ${LPATH}clean:rm -rf *_unit_test
make && ./hello_unit_test 编译并执行单测程序,执行结果如下:

gtest常用宏
1. 各种断言
1.1 Bool断言
| 致命断言 | 非致命断言 | 含义 |
|---|---|---|
| ASSERT_TRUE(val) | EXPECT_TRUE(val) | val == true |
| ASSERT_FALSE(val) | EXPECT_FALSE(val) | val == false |
1.2 二元值断言(比较大小)
| 致命断言 | 非致命断言 | 含义 |
|---|---|---|
| ASSERT_EQ(a, b) | EXPECT_EQ(a, b) | a == b |
| ASSERT_NE(a, b) | EXPECT_NE(a, b) | a != b |
| ASSERT_LT(a, b) | EXPECT_LT(a, b) | a < b |
| ASSERT_LE(a, b) | EXPECT_LE(a, b) | a <= b |
| ASSERT_GT(a, b) | EXPECT_GT(a, b) | a > b |
| ASSERT_GE(a, b) | EXPECT_GE(a, b) | a >= b |
1.3 字符串断言(字符串比较)
| 致命断言 | 非致命断言 | 含义 |
|---|---|---|
| ASSERT_STREQ(a, b) | EXPECT_STREQ(a, b) | a == b |
| ASSERT_STRNE(a, b) | EXPECT_STRNE(a, b) | a != b |
| ASSERT_STRCASEEQ(a, b) | EXPECT_STRCASEEQ(a, b) | a == b 忽略大小写 |
| ASSERT_STRCASENE(a, b) | EXPECT_STRCASENE(a, b) | a != b 忽略大小写 |
2. TEST、TEST_F和TEST_P
2.1 TEST
TEST是最基本的构造测试case的宏,基本用法:
TEST(param1, prama2)
{
/*测试代码*/
}
- 参数1:用例名,一般由待测试的类名或函数名组成,如TestAnimal
- 参数2:测试名,代表测试含义,如CaseEat
- 测试结果将以"用例名.测试名"来区分不同测试case
2.2 TEST_F
TEST_F和TEST的不同之处在于,其可以使用到初始化函数(SetUp)和一个清理函数(TearDown)。基本用法如下:
class TestAnimal : public ::testing::Test {
protected:void SetUp() override{// 成员变量初始化tigger = new Tigger();}void TearDown() override{// 资源清理、释放delete tigger;tigger = NULL;}
protected:Animal *tigger;
};TEST_F(TestAnimal, caseEatMeat)
{ // 执行之前调用SetUp进行初始化EXPECT_TRUE(tigger->eat("meat"));// case退出时调用TearDown进行释放
}TEST_F(TestAnimal, caseEatGrass)
{// 执行之前调用SetUp进行初始化EXPECT_FALSE(tigger->eat("grass"));// case退出时调用TearDown进行释放
}
- 创建一个继承testing::Test的测试类TestAnimal,并在该类中声明成员变量,做好初始化和清理操作
- TEST_F宏
- 参数1:同测试类名(TestAnimal )
- 参数2:测试名,代表测试含义
- 每一个测试case都是相互独立的,当每个case需要共同使用某个变量时,可以将该变量放在测试类中,每执行一个TEST_F宏构造的case,都会调用一次SetUp和TearDown,因此case之间对变量的操作不会相互影响。
2.3 TEST_P
针对某个待测试的方法,当你需要测试不同的输入,但又不想每个case都写一遍时,就可以使用到TEST_P宏,基本使用如下:
// 多个参数时,使用结构体更方便
struct MyParams {std::string food;// other params
};
class TestAnimal : public ::testing::Test, public ::testing::WithParamInterface<MyParams>
{
protected:void SetUp() override{// 成员变量初始化tigger = new Tigger();}void TearDown() override{// 资源清理、释放delete tigger;tigger = NULL;}
protected:Animal *tigger;
};TEST_P(TestAnimal, caseEat)
{std::string food = GetParam().food; // 获取参数ASSERT_FALSE(tigger->eat(food));
}// 构造不同的测试样例
INSTANTIATE_TEST_SUITE_P(TestCaseEatParams, TestAnimal, ::testing::Values(MyParams{"grass"},MyParams{"leafs"}
));
- 和TEST_F有相似的功能,使用SetUp、TearDown进行初始化和清理,创建一个继承testing::Test、testing::WithParamInterface的测试类,其中WithParamInterface是一个模板类,用来关联测试参数。
- TEST_P宏
- 参数1:测试类名
- 参数2:测试名,代表测试含义
- INSTANTIATE_TEST_SUITE_P宏
- 参数1:能表明测试含义即可
- 参数2:测试类名
- 参数3:不同测试样例集合
- 执行结果如下:

总结
- 好记性不如烂笔头,最近在写单元测试,于是就有了这篇文章。
- 通过学习gtest的基本语法,已经可以应对一部分测试场景了,然而还有一些场景只通过gtest是无法完成的,比如,在我们的代码中有许多并不是我们自己设计的接口,可能是外部依赖,也可能来自于其他模块,我们没办法设计一个合适的case来让这些接口返回给我们一个预期值,那我们该怎么办呢?于是gmock由此诞生,这个在下一篇中会进行深入学习,篇名我已经想好了(玩转单元测试之GMock)。
相关文章:
玩转单元测试之gtest
引言 程序开发的时候,往往需要编写一些测试样例来完成功能测试,以保证自己的代码在功能上符合预期,能考虑到一些异常边界问题等等。 gtest快速入门 1.引入gtest # 使用的是1.10版本,其他版本可根据需要选择 git clone -b v1.1…...
Tomcat 一次请求的生命周期
在使用 Tomcat 的时候,我们只需要在 Servlet 实现类中写我们的业务逻辑代码即可,不需要管 Socket 连接、协议处理要怎么实现,因为这部分作为不经常变动的部分,被封装到了 Tomcat 中,程序员只需要引入 Tomcat 中即可&am…...
spring cloud gateway中配置uri
gateway中配置uri配置有三种方式: websocket方式:uri: ws://localhost:9000http方式: uri: http://localhost:8130/lb注册中心配置方式(注册的服务名称): uri: lb://monitor-ms gateway的lb方式识别的服务名称命名规则: "[…...
使用NAudio录制wav音频
NAudio NAudio官网 环境 Unity2019.4.34f1c1 Window10 NAudio 1.10 .Net 3.5 录制音频 WaveInEvent类可录制音频 StartRecording方法 启用录制StopRecording方法 停止录制DataAvailable 录制中回调RecordingStopped 录制结束回调 WaveFileWriter类可存储音频 Write方法…...
数据结构之动态内存管理机制
目录 数据结构之动态内存管理机制 占用块和空闲块 系统的内存管理 可利用空间表 分配存储空间的方式 空间分配与回收过程产生的问题 边界标识法管理动态内存 分配算法 回收算法 伙伴系统管理动态内存 可利用空间表中结点构成 分配算法 回收算法 总结 无用单元收…...
【汇编语言】栈及栈操作的实现
文章目录 栈结构栈操作栈的小结 栈结构 栈是一种只能在一端插入或删除的数据结构;栈有两个基本的操作:入栈和出栈; 入栈:将一个新的元素放到栈顶;出栈:从栈顶取出一个元素; 栈的操作规则&#…...
【JavaEE】面向切面编程AOP是什么-Spring AOP框架的基本使用
【JavaEE】Spring AOP(1) 文章目录 【JavaEE】Spring AOP(1)1. Spring AOP 是什么1.1 AOP 与 Spring AOP1.2 没有AOP的世界是怎样的1.3 AOP是什么 2. Spring AOP 框架的学习2.1 AOP的组成2.1.1 Aspect 切面2.1.2 Pointcut 切点2.1…...
SpringBoot+微信小程序奶茶在线点单小程序系统 附带详细运行指导视频
文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码 一、项目演示 项目演示地址: 视频地址 二、项目介绍 项目描述:这是一个基于SpringBoot微信小程序框架开发的奶茶在线点单小程序系统。首先,这是一个前后端分离的项目ÿ…...
【支付宝小程序】开发基础--文件结构教程
🦖我是Sam9029,一个前端 Sam9029的CSDN博客主页:Sam9029的博客_CSDN博客-JS学习,CSS学习,Vue-2领域博主 🐱🐉🐱🐉恭喜你,若此文你认为写的不错,不要吝啬你的赞扬,求收…...
LLM 生成式配置的推理参数温度 top k tokens等 Generative configuration inference parameters
在这个视频中,你将了解一些方法和相关的配置参数,这些参数可以用来影响模型在下一个词生成时的最终决策方式。如果你在Hugging Face网站或AWS的游乐场中使用过LLMs,你可能已经看到了这些控制选项,用来调整LLM的行为。每个模型都暴…...
npm的镜像源和代理的查看和修改
一、镜像源 查询当前镜像源 npm get registry 设置为淘宝镜像 npm config set registry http://registry.npm.taobao.org/ 设置回默认的官方镜像 npm config set registry https://registry.npmjs.org/ 设置electron为淘宝镜像 npm config set ELECTRON_MIRROR "h…...
IP库新增经过实践的Verilog 库
网上严重缺乏实用的 Verilog 设计。Project F 库是尝试让 FPGA 初学者变得更好部分。 设计包括 Clock- 时钟生成 (PLL) 和域交叉Display - 显示时序、帧缓冲区、DVI/HDMI 输出Essential- 适用于多种设计的便捷模块Graphics- 绘制线条和形状Maths- 除法、LFSR、平方根、正弦....…...
SLAM-VIO视觉惯性里程计
SLAM 文章目录 SLAM前言IMU与视觉比较单目视觉缺陷:融合IMU优势:相机-IMU标定松耦合紧耦合基于滤波的融合方案:基于优化的融合方案: 前言 VIO(visual-inertial odometry)即视觉惯性里程计,有时…...
分布式 RPC 框架入门
分布式 RPC 框架入门 警告 torch.distributed.rpc 程序包是实验性的,随时可能更改。 它还需要 PyTorch 1.4.0才能运行,因为这是第一个支持 RPC 的版本。 本教程使用两个简单的示例来演示如何使用 torch.distributed.rpc 软件包构建分布式训练…...
Spring boot与Spring cloud 之间的关系
Spring boot与Spring cloud 之间的关系 Spring boot 是 Spring 的一套快速配置脚手架,可以基于spring boot 快速开发单个微服务,Spring Boot,看名字就知道是Spring的引导,就是用于启动Spring的,使得Spring的学习和使用…...
报名开启 | HarmonyOS第一课“营”在暑期系列直播
<HarmonyOS第一课>2023年再次启航! 特邀HarmonyOS布道师云集华为开发者联盟直播间 聚焦HarmonyOS 4版本新特性 邀您一同学习赢好礼! 你准备好了吗? ↓↓↓预约报名↓↓↓ 点击关注了解更多资讯,报名学习...
Apache DolphinScheduler 支持使用 OceanBase 作为元数据库啦!
DolphinScheduler是一个开源的分布式任务调度系统,拥有分布式架构、多任务类型、可视化操作、分布式调度和高可用等特性,适用于大规模分布式任务调度的场景。目前DolphinScheduler支持的元数据库有Mysql、PostgreSQL、H2,如果在业务中需要更好…...
matlab使用教程(17)—广度优先和深度优先搜索
1.可视化广度优先搜索和深度优先搜索 此示例说明如何定义这样的函数:该函数通过突出显示图的节点和边来显示 bfsearch 和 dfsearch 的可视化结果。 创建并绘制一个有向图。 s [1 2 3 3 3 3 4 5 6 7 8 9 9 9 10]; t [7 6 1 5 6 8 2 4 4 3 7 1 6 8 2]; G dig…...
CSerialPort教程4.3.x (2) - CSerialPort源码简介
CSerialPort教程4.3.x (2) - CSerialPort源码简介 前言 CSerialPort项目是一个基于C/C的轻量级开源跨平台串口类库,可以轻松实现跨平台多操作系统的串口读写,同时还支持C#, Java, Python, Node.js等。 CSerialPort项目的开源协议自 V3.0.0.171216 版本…...
【数据结构OJ题】有效的括号
原题链接:https://leetcode.cn/problems/valid-parentheses/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 这道题目主要考查了栈的特性: 题目的意思主要是要做到3点匹配:类型、顺序、数量。 题目给的例子是比较…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
《Docker》架构
文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...
Spring Boot + MyBatis 集成支付宝支付流程
Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例(电脑网站支付) 1. 添加依赖 <!…...
Matlab实现任意伪彩色图像可视化显示
Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的亮度(或…...
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...
