玩转单元测试之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点匹配:类型、顺序、数量。 题目给的例子是比较…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...

GraphQL 实战篇:Apollo Client 配置与缓存
GraphQL 实战篇:Apollo Client 配置与缓存 上一篇:GraphQL 入门篇:基础查询语法 依旧和上一篇的笔记一样,主实操,没啥过多的细节讲解,代码具体在: https://github.com/GoldenaArcher/graphql…...