gtest 框架

news2024/11/20 9:37:05

基本了解

google提供的一个C++测试框架,主要就是简化测试单元的书写,具有高效、灵活可拓展的特点

主要特点

  • 简单易用:gtest 提供了清晰且易于使用的 API,便于开发者快速编写单元测试。
  • 丰富的断言支持:gtest 提供了多种断言(assertion)来验证不同类型的条件(如 EXPECT_EQASSERT_TRUE 等),使得测试结果的验证更为精确。
  • 支持测试夹具 (Test Fixtures):允许在多个测试间共享测试环境和资源,避免重复代码。
  • 自动化测试结果报告:gtest 会自动生成测试的执行结果,报告哪些测试通过,哪些失败。
  • 兼容性:gtest 能够与多种构建系统(如 CMake)集成,并且可以与持续集成工具一起使用。
  • 跨平台支持:支持 Windows、Linux、Mac 等操作系统,能够运行在各种开发环境下。
  • 扩展性:你可以根据需要扩展 gtest 提供的功能,比如自定义断言或添加新的测试功能。

基本概念

  • 测试案例 (Test Case): 测试案例是一个包含一个或多个测试的类。每个测试类继承自 ::testing::Test,并包含测试代码和测试夹具(如果需要的话)
  • 测试夹具 (Test Fixture): 测试夹具是指在多个测试中需要共享的环境或状态,通常用于在测试开始之前进行一些初始化工作,测试结束后进行清理。通过继承 ::testing::Test 类来创建
  • 测试套件 (Test Suite): 测试套件由多个测试案例(Test Case)组成,它们共享相同的测试环境。每个测试案例是一个测试类,包含一个或多个测试方法
  • 断言 (Assertions)(重点): 断言用于验证程序的行为是否符合预期,gtest 提供了多种断言
    • EXPECT_EQ(val1, val2):期望 val1val2 相等(不等时记录失败,但继续执行)。
    • ASSERT_EQ(val1, val2):期望 val1val2 相等(不等时会终止当前测试)。
    • EXPECT_TRUE(condition):期望条件为真。
    • EXPECT_FALSE(condition):期望条件为假。
    • ASSERT_TRUE(condition):期望条件为真,并终止当前测试(如果不为真)。
    • ASSERT_FALSE(condition):期望条件为假,并终止当前测试(如果不为假)。
  • 测试运行器 (Test Runner): gtest 使用一个测试运行器来执行所有的测试并报告结果,通常我们通过命令行运行测试可执行文件来启动测试运行

初步上手使用

测试简单加法运算

#include<iostream>
#include<gtest/gtest.h>

int add(int x , int y)
{
    return x+y;
}

TEST(函数测试,加法函数测试1)
{
    //判断最终结果是否为40
    ASSERT_EQ(add(20,20),40);
    ASSERT_LT(add(10,10),30);
}

TEST(函数测试, 字符串测试)
{
    std::string str = "hello gtest";
    ASSERT_EQ(str, std::string("hello gtest"));  // 类型一致
    ASSERT_EQ(str, std::string("hello world")); // 比较失败
}


int main(int argc,char *argv[])
{
    testing::InitGoogleTest(&argc,argv);
    //运行所有测试用例
    return RUN_ALL_TESTS();
}

 EXPECT_EQ(val1, val2)ASSERT_EQ(val1, val2)

  • EXPECT_EQ:如果断言失败,测试继续执行
  • ASSERT_EQ:如果断言失败,当前测试停止执行

#include <gtest/gtest.h>
#include <iostream>

int add(int a, int b) {
    return a + b;
}

TEST(AddTest, PositiveNumbers) {
    EXPECT_EQ(add(2, 3), 5);  // 这条断言通过
    EXPECT_EQ(add(1, 1), 3);  // 这条断言失败,但测试继续执行
}

TEST(AddTest, AssertEqual) {
    ASSERT_EQ(add(2, 3), 5);  // 通过
    std::cout<<"测试输出:assert_eq前"<<std::endl;
    ASSERT_EQ(add(1, 1), 3);  // 失败,当前测试停止
    std::cout<<"测试输出:assert_eq后"<<std::endl;

}


int main(int argc,char *argv[])
{
    testing::InitGoogleTest(&argc,argv);
    //运行所有测试用例
    return RUN_ALL_TESTS();
}

EXPECT_NE(val1, val2)ASSERT_NE(val1, val2)

TEST(AddTest, NotEqual) {
    EXPECT_NE(add(2, 3), 6);  // 通过
    EXPECT_NE(add(2, 2), 5);  // 通过
    ASSERT_NE(add(2, 3), 6);  // 通过
    ASSERT_NE(add(1, 1), 3);  // 失败,测试停止(注意该处是不会打印错误的,直接就退出了)
}

 EXPECT_LT(val1, val2)ASSERT_LT(val1, val2)

 验证val1是否小于val2

TEST(ComparisonTest, LessThan) {
    EXPECT_LT(2, 3);  // 通过
    EXPECT_LT(5, 3);  // 失败,测试继续
    ASSERT_LT(2, 3);  // 通过
    ASSERT_LT(5, 3);  // 失败,测试停止
}

 EXPECT_LE(val1, val2)ASSERT_LE(val1, val2)

 验证val1是否小于或者等于val2

TEST(ComparisonTest, LessThanOrEqual) {
    EXPECT_LE(2, 3);  // 通过
    EXPECT_LE(3, 3);  // 通过
    EXPECT_LE(5, 3);  // 失败,测试继续
    ASSERT_LE(2, 3);  // 通过
    ASSERT_LE(3, 3);  // 通过
    ASSERT_LE(5, 3);  // 失败,测试停止
}

 XPECT_GT(val1, val2)ASSERT_GT(val1, val2)

 验证 val1 是否大于 val2

TEST(ComparisonTest, GreaterThan) {
    EXPECT_GT(3, 2);  // 通过
    EXPECT_GT(2, 3);  // 失败,测试继续
    ASSERT_GT(3, 2);  // 通过
    ASSERT_GT(2, 3);  // 失败,测试停止
}

 EXPECT_GE(val1, val2)ASSERT_GE(val1, val2)

 验证 val1 是否大于或等于 val2

TEST(ComparisonTest, GreaterThanOrEqual) {
    EXPECT_GE(3, 2);  // 通过
    EXPECT_GE(3, 3);  // 通过
    EXPECT_GE(2, 3);  // 失败,测试继续
    ASSERT_GE(3, 2);  // 通过
    ASSERT_GE(3, 3);  // 通过
    ASSERT_GE(2, 3);  // 失败,测试停止
}

 EXPECT_TRUE(condition)ASSERT_TRUE(condition)

 验证 condition 是否为 true

TEST(ConditionTest, IsTrue) {
    EXPECT_TRUE(2 + 3 == 5);  // 通过
    EXPECT_TRUE(2 + 3 == 6);  // 失败,测试继续

    ASSERT_TRUE(2 + 3 == 5);  // 通过
    ASSERT_TRUE(2 + 3 == 6);  // 失败,测试停止
}

 EXPECT_THROW(statement, exception)ASSERT_THROW(statement, exception)

 断言用于验证执行某个语句时是否抛出了特定类型的异常

  • EXPECT_THROW:如果没有抛出异常,测试继续执行
  • ASSERT_THROW:如果没有抛出异常,测试立即停止

#include <gtest/gtest.h>
#include <iostream>

#include <stdexcept>

void throw_exception() {
    throw std::runtime_error("An error occurred");
}

TEST(ExceptionTest, ThrowException) {
    EXPECT_THROW(throw_exception(), std::runtime_error);  // 通过
    EXPECT_THROW(throw_exception(), std::invalid_argument);  // 失败,测试继续

    ASSERT_THROW(throw_exception(), std::runtime_error);  // 通过
    ASSERT_THROW(throw_exception(), std::invalid_argument);  // 失败,测试停止
}


int main(int argc,char *argv[])
{
    testing::InitGoogleTest(&argc,argv);
    //运行所有测试用例
    return RUN_ALL_TESTS();
}

 EXPECT_NO_THROW(statement)ASSERT_NO_THROW(statement)

用于验证语句没有抛出异常,参考上面

TEST(ExceptionTest, NoThrow) {
    EXPECT_NO_THROW(throw_exception());  // 失败,测试继续
    EXPECT_NO_THROW(int x = 5);  // 通过

    ASSERT_NO_THROW(throw_exception());  // 失败,测试停止
    ASSERT_NO_THROW(int x = 5);  // 通过
}

动态库编译问题 

问题复现

#include<iostream>
#include<gtest/gtest.h>

int add(int x , int y)
{
    return x+y;
}

TEST(函数测试,加法函数测试1)
{
    //判断最终结果是否为40
    ASSERT_EQ(add(20,20),40);
    ASSERT_LT(add(10,10),30);
}

// TEST(函数测试, 字符串测试)
// {
//     std::string str = "hello gtest";
//     ASSERT_EQ(str, std::string("hello gtest"));  // 类型一致
//     ASSERT_EQ(str, std::string("hello world")); // 比较失败
// }


int main(int argc,char *argv[])
{
    testing::InitGoogleTest(&argc,argv);
    //运行所有测试用例
    return RUN_ALL_TESTS();
}
main : main.cc
	g++ -std=c++17 $^ -o $@ -lgtest 

解决思路

无法查找到gtest动态库

重新安装,然后生成动态库

 通过源码并进行编译

 在构建目录下安装并生成动态库

 动态库安装完毕,重新编译程序验证

编译成功,但是运行失败

分析:这个是动态库路径没有正常配置导致的,先通过环境变量,显式的指定动态库路径,尝试是否可以解决问题;先判断路径,然后显式指定

永久性配置动态链接库路径

通过命令将动态库路径加入到系统的动态库链接器配置中

问题解决 

反思总结

sudo apt-get install libgtest-dev没有生成动态库的原因

Ubuntu官方的 libgtest-dev的包只提供 gtest的源码,不会自动生成静态库和动态库,这个是提供给使用者根据项目的需要动态决定自己构建动态库

gtest默认是以静态库进行使用,自己手动编译默认生成的也是静态库,如果需要动态库,那么必须显式的启用BUILD_SHARED_LIBS=ON的CMake配置选项

一个Build文件造成静态库和动态库冲突位问题

如果在Build目录中生成了缓存文件,这些缓存文件会固定CMake的构建配置选项,所以如果已经有静态库的缓存文件,此时再使用生成动态库,就会导致动态库使用静态库的缓存,所以最终就会导致错误

解决该问题的办法有两个,其一是给静态库和动态库分别构建一个Build文件夹,其二则是先清理旧的换存然后再生成

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2243961.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习—误差分析

帮助运行诊断的最重要的方法是选择下一步要尝试的内容&#xff0c;提高你的学习算法性能&#xff0c;偏差和方差可能是最重要的想法&#xff0c;然后是错误分析。 假设Mcv500&#xff0c;即有500个交叉验证示例&#xff0c;你的算法错误的分类了100个&#xff0c;错误分析过程…

微知-如何查看BlueField DPU上的内存信息,包括内存主频和位宽?(dmidecode -t memory)

背景 在定位DPU上网卡性能的时候&#xff0c;可能涉及到查看内存的主频、位宽、电压等信息&#xff0c;如何快速查看&#xff1f; 命令 dmidecode -t memory实操 可以看到主频是 3200MT/s&#xff0c;另外还能看到位宽&#xff0c;大小&#xff0c;电压等信息。

【AI系统】AI系统架构的组成

AI 系统组成 如图所示&#xff0c;大致可以将 AI 系统分为以下几个具体的方向&#xff1a; AI 训练与推理框架 AI 框架不仅仅是指如 PyTorch 等训练框架&#xff0c;还包括推理框架。其负责提供用户前端的 AI 编程语言&#xff0c;接口和工具链。负责静态程序分析与计算图构建…

竞赛思享会 | 2024年第十届数维杯国际数学建模挑战赛D题【代码+演示】

Hello&#xff0c;这里是Easy数模&#xff01;以下idea仅供参考&#xff0c;无偿分享&#xff01; 题目背景 本题旨在通过对中国特定城市的房产、人口、经济、服务设施等数据进行分析&#xff0c;评估其在应对人口老龄化、负增长趋势和极端气候事件中的韧性与可持续发展能力。…

机器学习基础07

目录 1.逻辑回归 1.1原理 1.2API 2.K-Means 2.1算法过程 2.2API 3.SVM&#xff08;支持向量机&#xff09; 3.1算法原理​ 3.2API 1.逻辑回归 逻辑回归(Logistic Regression)是机器学习中的一种分类模型&#xff0c;逻辑回归是一种分类算法。 1.1原理 逻辑回归的输…

基于python的在线投票系统小程序u9t2g.

目录 项目介绍开发技术具体实现截图微信开发者工具介绍技术路线开发语言以及框架介绍python-flask核心代码部分展示python-django核心代码部分展示详细视频演示源码获取 项目介绍 投票系统用户端是基于微信小程序&#xff0c;管理员端是基于web网页端&#xff0c; &#xff0c…

android 使用MediaPlayer实现音乐播放--权限请求

在Android应用中&#xff0c;获取本地音乐文件的权限是实现音乐扫描功能的关键步骤之一。随着Android版本的不断更新&#xff0c;从Android 6.0&#xff08;API级别23&#xff09;开始&#xff0c;应用需要动态请求权限&#xff0c;而到了android 13以上需要的权限又做了进一步…

向量数据库FAISS之五:原理(LSH、PQ、HNSW、IVF)

1.Locality Sensitive Hashing (LSH) 使用 Shingling MinHashing 进行查找 左侧是字典&#xff0c;右侧是 LSH。目的是把足够相似的索引放在同一个桶内。 LSH 有很多的版本&#xff0c;很灵活&#xff0c;这里先介绍第一个版本&#xff0c;也是原始版本 Shingling one-hot …

【SQL】E-R模型(实体-联系模型)

目录 一、介绍 1、实体集 定义和性质 属性 E-R图表示 2. 联系集 定义和性质 属性 E-R图表示 一、介绍 实体-联系数据模型&#xff08;E-R数据模型&#xff09;被开发来方便数据库的设计&#xff0c;它是通过允许定义代表数据库全局逻辑结构的企业模式&#xf…

SIMCom芯讯通A7680C在线升级:FTP升级成功;http升级腾讯云对象储存的文件失败;http升级私有服务器的文件成功

从事嵌入式单片机的工作算是符合我个人兴趣爱好的,当面对一个新的芯片我即想把芯片尽快搞懂完成项目赚钱,也想着能够把自己遇到的坑和注意事项记录下来,即方便自己后面查阅也可以分享给大家,这是一种冲动,但是这个或许并不是原厂希望的,尽管这样有可能会牺牲一些时间也有哪天原…

如何理解岭回归模型?(python)

1 何为岭回归&#xff1f; 岭参数k不是唯一确定的&#xff0c;其估计的回归系数是一个估计族。 2 何为岭迹分析&#xff1f; 1&#xff09;定义 2&#xff09;作用 k值的选取原则&#xff1a; 如下图所示&#xff0c;当kk0时&#xff0c;各回归系数的估计值基本都能相对稳…

Prometheus结合K8s(二)使用

上一篇介绍了如何搭建 Prometheus结合K8s&#xff08;一&#xff09;搭建-CSDN博客&#xff0c;这章介绍使用 页面访问 kubectl get svc -n prom 看promeheus和granfana的端口访问页面 Prometheus 点击status—target&#xff0c;可以看到metrics的数据来源&#xff0c;即各…

泷羽sec学习打卡-云技术基础2-捕获照片

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负 关于云技术基础的那些事儿-捕获帅照 搭建网站的前提有哪些&#xff1f;搭建网站的流程有哪些&#xff1f…

常见的水位检测传感器及其特点

常见的水位检测传感器及其特点&#xff1a; 1. 浮球液位传感器&#xff1a; - 工作原理&#xff1a;利用浮力&#xff0c;使浮子上升&#xff0c;通过判断浮子上升来判断水位 -优点&#xff1a;便宜简单 - 缺点&#xff1a;精确度低&#xff0c;应用环境受限。靠液体的浮力…

Flink Lookup Join(维表 Join)

Lookup Join 定义&#xff08;支持 Batch\Streaming&#xff09; Lookup Join 其实就是维表 Join&#xff0c;比如拿离线数仓来说&#xff0c;常常会有用户画像&#xff0c;设备画像等数据&#xff0c;而对应到实时数仓场景中&#xff0c;这种实时获取外部缓存的 Join 就叫做维…

Azure Kubernetes Service (AKS)资源优化策略

针对Azure Kubernetes Service (AKS)的资源优化策略&#xff0c;可以从多个维度进行考虑和实施&#xff0c;以提升集群的性能、效率和资源利用率。以下是一些关键的优化策略&#xff1a; 一、 Pod资源请求和限制 设置Pod请求和限制&#xff1a;在YAML清单中为所有Pod设置CPU和…

RabbitMQ1:初识MQ

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

AI 提示词(Prompt)入门 十:最佳实践|详细询问,提供细节!

1、原则解释 当与 ChatGPT 交流时&#xff0c;提供具体和详细的信息非常重要。 这样做可以帮助 ChatGPT 更准确地理解你的需求和上下文&#xff0c;从而生成更相关和有用的回答 明确的信息可以包括具体的问题背景、相关领域的说明、你所期望的答案类型等。 2、如何实践 明…

实验十三 生态安全评价

1 背景及目的 生态安全是生态系统完整性和健康性的整体反映&#xff0c;完整健康的生态系统具有调节气候净化污染、涵养水源、保持水土、防风固沙、减轻灾害、保护生物多样性等功能。维护生态安全对于人类生产、生活、健康及可持续发展至关重要。随着城市化进程的不断推进&…

怎样实现跨部门和跨地区的数据共享?

随着企业规模的扩大和业务的多样化&#xff0c;不同部门和地区之间的数据共享变得越来越重要。实时数据同步作为保证数据准确性和完整性的重要手段&#xff0c;被广泛应用于各行各业。那不同部门和不同地区怎么实现共享数据呢&#xff1f; 一、前期数据准备 前期数据上需要建…