当前位置: 首页 > news >正文

googletest 笔记

什么是一个好的测试

1 测试应该是独立的和可重复的。调试一个由于其他测试而成功或 失败的测试是一件痛苦的事情。googletest 通过在不同的对象上 运行测试来隔离测试。当测试失败时,googletest 允许您单独运 行它以快速调试。

2 测试应该很好地“组织”,并反映出测试代码的结构。googletest 将相关测试分组到可以共享数据和子例程的测试套件中。这种通 用模式很容易识别,并使测试易于维护。当人们切换项目并开始 在新的代码库上工作时,这种一致性尤其有用。 3 测试应该是可移植的和可重用的。谷歌有许多与平台无关的代 码;它的测试也应该是平台中立的。googletest 可以在不同的操 作系统上工作,使用不同的编译器,所以 googletest 测试可以在 多种配置下工作。

4 当测试失败时,他们应该提供尽可能多的关于问题的信息。 googletest 不会在第一次测试失败时停止。相反,它只停止当前 的测试并继续下一个测试。还可以设置报告非致命失败的测试, 在此之后当前测试将继续进行。因此,您可以在一个运行-编辑编译周期中检测和修复多个错误。

5 测试框架应该将测试编写者从日常琐事中解放出来,让他们专注 于测试“内容”。googletest 自动跟踪所有定义的测试,并且不要 求用户为了运行它们而枚举它们

6 测试应该是快速的。使用 googletest,您可以在测试之间重用共 享资源,并且只需要为设置/拆除支付一次费用,而无需使测试 彼此依赖。

测试层次关系

环境准备

下载

git clone https://github.com/google/googletest.git # 或者 wget https://github.com/google/googletest/releases/tag/ release-1.11.0

安装

cd googletest cmake CMakeLists.txt make sudo make install

重要文件

googletest
# 头文件 gtest/gtest.h # 不带 main 静态库 libgtest.a # 带 main 静态库 libgtest_main.a 当不想写 main 函数的时候,可以直接引入 libgtest_main.a;
g++ sample.cc -o sample -lgtest -lgtest_main - lpthread g++ sample.cc -o sample -lgtest -lgmock - lgmock_main -lpthread 否则 g++ sample.cc -o sample -lgtest -lpthread g++ sample.cc -o sample -lgtest -lgmock - lpthread
googlemock # 头文件 gmock/gmock.h # 不带 main 静态库 libgmock.a # 带 main 静态库 libgmock_main.a

断言

断言成对出现,它们测试相同的东西,但对当前函数有不同的 影响。ASSERT_*版本在失败时产生致命失败,并中止当前测试 案例。EXPECT_*版本生成非致命失败,它不会中止当前函数。 通常首选EXPECT_*,因为它们允许在测试中报告一个以上的失 败。但是,如果在有问题的断言失败时继续没有意义,则应该 使用ASSERT_*。 所有断言宏都支持输出流,也就是当出现错误的时候,我们可 以通过流输出更详细的信息;注意编码问题,经流输出的信息 会自动转换为 UTF-8;
EXPECT_TRUE(my_condition) << "My condition is not true";

明确指定成功或者失败

有时候我们测试案例当中的条件太复杂,不能使用断言,那么 自己写判断语句;自己返回成功或者失败;SUCCEED() 或者 FAIL()

布尔条件
EXPECT_TRUE( condition ) ASSERT_TRUE( condition ) EXPECT_FALSE( condition ) ASSERT_FALSE( condition )

二元比较

val1 = val2:

EXPECT_EQ( val1 , val2 )

ASSERT_EQ( val1 , val2 )

val1 != val2:

EXPECT_NE( val1 , val2 )

ASSERT_NE( val1 , val2 )

注意:比较空指针的时候;

使用 EXPECT_NE( ptr , nullptr) 而不是 EXPECT_NE( ptr , NULL)。

val1 < val2:

EXPECT_LT( val1 , val2 )

ASSERT_LT( val1 , val2 )

val1 <= val2: EXPECT_LE( val1 , val2 ) ASSERT_LE( val1 , val2 ) val1 > val2: EXPECT_GT( val1 , val2 ) ASSERT_GT( val1 , val2 ) val1 >= val2: EXPECT_GE( val1 , val2 ) ASSERT_GE( val1 , val2 )

谓词断言

谓词断言能比 EXPECT_TRUE 提供更详细的错误消息;
EXPECT_PRED1( pred , val1 ) \
EXPECT_PRED2( pred , val1 , val2 ) \
EXPECT_PRED3( pred , val1 , val2 , val3 ) \
EXPECT_PRED4( pred , val1 , val2 , val3 , val4 ) \
EXPECT_PRED5( pred , val1 , val2 , val3 , val4 , val5 )
ASSERT_PRED1( pred , val1 ) \
ASSERT_PRED2( pred , val1 , val2 ) \
ASSERT_PRED3( pred , val1 , val2 , val3 ) \
ASSERT_PRED4( pred , val1 , val2 , val3 , val4 ) \
ASSERT_PRED5( pred , val1 , val2 , val3 , val4 , val5 )// Returns true if m and n have no common divisors
except 1.
bool MutuallyPrime(int m, int n) { ... }
...
const int a = 3;
const int b = 4;
const int c = 10;
...
EXPECT_PRED2(MutuallyPrime, a, b);  // Succeeds
EXPECT_PRED2(MutuallyPrime, b, c);  // Fails
能得到错误信息:
MutuallyPrime(b, c) is false, where
b is 4
c is 10

googletest samples 层次

函数测试以及类测试

#define TEST(test_suite_name,test_name)

test fixture(测试夹具)

用相同的数据配置来测试多个测试案例。

// 定义类型,继承自 testing::Test
class TestFixtureSmpl : public testing::Test {
protected:void SetUp() {} // 测试夹具测试前调用的函数 -- 做初
始化的工作void TearDown() {} // 测试夹具测试后调用的函数 --
做清理的工作
};
// 需要在 TEST_F 中书写测试用例
#define TEST_F(test_fixture,test_name)
// 如果需要复用测试夹具,只需要继承自 TestFixtureSmpl
class TestFixtureSmpl_v2 : public TestFixtureSmpl
{
};

类型参数化

有时候相同的接口,有多个实现,下面是复用测试代码流程;复用测试案例,策略模式 using testing::Test;
using testing::Types;
// 先申明测试夹具
template <class T>
class TestFixtureSmpl : public testing::Test {
protected:void SetUp() {} // 测试夹具测试前调用的函数 -- 做初
始化的工作void TearDown() {} // 测试夹具测试后调用的函数 --
做清理的工作
};
// 枚举测试类型
typedef Types<Class1, Class2, class3, ...>
Implementations;
// #define
TYPED_TEST_SUITE(CaseName,Types,__VA_ARGS__...)
// 注意 casename 一定要与测试夹具的名字一致
TYPED_TEST_SUITE(TestFixtureSmpl,
Implementations);
// #define TYPED_TEST(CaseName,TestName)
// 开始测试, CaseName 要与 TYPED_TEST_SUITE 一致
TYPED_TEST(TestFixtureSmpl, TestName)有时候你写了某个接口,期望其他人实现它,你可能想写一系列测试,确保其他人的实现满足你的测试;
// 首先声明测试类型参数化(_P 是 parameterized or
pattern)
// #define TYPED_TEST_SUITE_P(SuiteName)
TYPED_TEST_SUITE_P(TestFixtureSmpl);
// 书写测试, suiteName 与上面一致
// #define TYPED_TEST_P(SuiteName,TestName)
TYPED_TEST_P(TestFixtureSmpl,TestName)
// 枚举所有测试
// #define
REGISTER_TYPED_TEST_SUITE_P(SuiteName,__VA_ARGS__
...)
REGISTER_TYPED_TEST_SUITE_P(TestFixtureSmpl,
TestName1,TestName2,...)
// 上面定义的是抽象测试类型
// 其他人实现功能后,开始测试,假如实现了
OnTheFlyPrimeTable 和 PreCalculatedPrimeTable
typedef Types<OnTheFlyPrimeTable,
PreCalculatedPrimeTable>PrimeTableImplementations;
// #define
INSTANTIATE_TYPED_TEST_SUITE_P(Prefix,SuiteName,T
ypes,__VA_ARGS__...)
INSTANTIATE_TYPED_TEST_SUITE_P(instance_name,testcase,typelist...)

事件

可以通过 googletest 的事件机制,在测试前后进行埋点处理;
// The interface for tracing execution of tests.
The methods are organized in
// the order the corresponding events are fired.
class TestEventListener {
public:virtual ~TestEventListener() {}// Fired before any test activity starts.virtual void OnTestProgramStart(const UnitTest& unit_test) = 0;// Fired before each iteration of tests starts. There may be more than// one iteration if GTEST_FLAG(repeat) is set. iteration is the iteration// index, starting from 0.virtual void OnTestIterationStart(const UnitTest& unit_test,int iteration) = 0;
// Fired before environment set-up for eachiteration of tests starts.virtual void OnEnvironmentsSetUpStart(const UnitTest& unit_test) = 0;// Fired after environment set-up for eachiteration of tests ends.virtual void OnEnvironmentsSetUpEnd(const UnitTest& unit_test) = 0;// Fired before the test suite starts.virtual void OnTestSuiteStart(const TestSuite& /*test_suite*/) {}// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_// Fired before the test starts.virtual void OnTestStart(const TestInfo& test_info) = 0;// Fired after a failed assertion or a SUCCEED() invocation.// If you want to throw an exception from this function to skip to the next// TEST, it must be AssertionException defined above, or inherited from it.virtual void OnTestPartResult(const TestPartResult& test_part_result) = 0;// Fired after the test ends.virtual void OnTestEnd(const TestInfo& test_info) = 0;// Fired after the test suite ends.virtual void OnTestSuiteEnd(const TestSuite& /*test_suite*/) {}// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_virtual void OnTestCaseEnd(const TestCase& /*test_case*/) {}
#endif  // GTEST_REMOVE_LEGACY_TEST_CASEAPI_// Fired before environment tear-down for each iteration of tests starts.virtual void OnEnvironmentsTearDownStart(const UnitTest& unit_test) = 0;// Fired after environment tear-down for each iteration of tests ends.virtual void OnEnvironmentsTearDownEnd(const UnitTest& unit_test) = 0;// Fired after each iteration of tests finishes.virtual void OnTestIterationEnd(const UnitTest& unit_test,int iteration) = 0;// Fired after all test activities have ended.virtual void OnTestProgramEnd(const UnitTest& unit_test) = 0;
};

内存泄露

怎么产生?1. 忘记释放了;2. 因为逻辑bug,跳过了释放流 程; new 是 c++ 中的操作符; 1. 调用 operator new 分配内存; 2. 调用构造函数在步骤 1 返回的内存地址生成类对象; 可以通过重载 new 来修改 1 的功能; delete 与 new 类似;只是是先调用析构函数,再释放内存;
// 重载操作符 new 和 delete,接着用类的静态成员来统计调
用 new 和 delete的次数
class CLeakMem {
public:// ...void* operator new(size_t allocation_size) {allocated_++;return malloc(allocation_size);}void operator delete(void* block, size_t /*
allocation_size */) {allocated_--;free(block);}
private:static int allocated_;
};
int CLeakMem::allocated_ = 0;
检测
class LeakChecker : public EmptyTestEventListener
{
private:// Called before a test starts.void OnTestStart(const TestInfo& /* test_info*/) override {initially_allocated_ = CLeakMem::allocated();}// Called after a test ends.void OnTestEnd(const TestInfo& /* test_info */) override {int difference = CLeakMem::allocated() - initially_allocated_;// You can generate a failure in any event handler except// OnTestPartResult. Just use an appropriate Google Test assertion to do// it.EXPECT_LE(difference, 0) << "Leaked " << difference << " unit(s) of class!";}int initially_allocated_;
};

相关文章:

googletest 笔记

什么是一个好的测试 1 测试应该是独立的和可重复的。调试一个由于其他测试而成功或 失败的测试是一件痛苦的事情。googletest 通过在不同的对象上 运行测试来隔离测试。当测试失败时&#xff0c;googletest 允许您单独运 行它以快速调试。 2 测试应该很好地“组织”&#xff0c…...

MySQL修改密码的几种方式?

第一种方式&#xff1a; 最简单的方法就是借助第三方工具Navicat for MySQL来修改。方法如下&#xff1a; 1、登录mysql到指定库&#xff0c;如&#xff1a;登录到test库。 2、然后点击上方"用户"按钮。 3、选择要更改的用户名&#xff0c;然后点击上方的"编辑用…...

关于画一个句号--基于2022年终总结的反思与分享

没有平台鼓风造势&#xff0c;今年各大平台没有涌现出一批总结&#xff0c;非常清爽 正如同人发明了抽屉&#xff0c;将杂物进行整理、丢弃、收纳&#xff0c;才能对空间进行更合理地使用。我们也需要对知识、过往经历进行整理、丢弃、收纳&#xff0c;才能对大脑进行更合理地…...

学习Flask之三、模板

学习Flask之三、模板 书写易于维护的应用的关键是书写整洁和良构的代码。到目前为止你所见的例子过于简单而不能体现这点。把两个目的完全独立的Flask view 函数当作一个来写&#xff0c;会产生问题。view函数的一个显然的任务是对请求作出响应&#xff0c;如前面的例子所示。对…...

2023-02-20干活小计:

所以我今天的活开始了&#xff1a; In this paper, the authors target the problem of Multimodal Name Entity Recognition(MNER) as an improvement on NER(text only) The paper proposes a multimodal fusion based on a heterogeneous graph of texts and images to mak…...

LeetCode_动态规划_困难_1326.灌溉花园的最少水龙头数目

目录1.题目2.思路3.代码实现&#xff08;Java&#xff09;1.题目 在 x 轴上有一个一维的花园。花园长度为 n&#xff0c;从点 0 开始&#xff0c;到点 n 结束。 花园里总共有 n 1 个水龙头&#xff0c;分别位于 [0, 1, …, n] 。 给你一个整数 n 和一个长度为 n 1 的整数数…...

mac tcpdump学习

学习原因 工作上遇到了重启wifi后无法发出mDNS packet的情况&#xff0c;琢磨一下用tcpdump用的命令如下 sudo tcpdump -n -k -s 0 -i en0 -w VENDOR-DUT-INTERFACE.pcapng是在测airplay BCT认证时&#xff0c;官方文档的解决方法。对tcpdump很不了解&#xff0c;现汇总如下的学…...

【跟我一起读《视觉惯性SLAM理论与源码解析》】第二章 编程及编译工具

23.2.21终于拿到六哥的新书 感觉很是不错&#xff0c;打算近期写一写心得之类的 废话不多说&#xff0c;直接开啃 PS&#xff1a;我的建议是阅读完十四讲后再来看这本书&#xff0c;效果应该会很不错。 因为第一章都是介绍之类的我觉得没什么整理的必要&#xff0c;所以直接来…...

广东望京卡牌科技有限公司,2023年团建活动圆满举行

玉兔初临&#xff0c;春天相随&#xff0c;抖擞精神&#xff0c;好运连连。春天是一个万物复苏的季节&#xff0c;来自广东的望京卡牌科技有限公司&#xff0c;也迎来了新年第一次团建活动。在“乘风破浪、追逐梦想”的口号声中&#xff0c;2023望京卡牌目标启动会团结活动正式…...

ts语法如何在Vue3中运用?

一、父子传值的用法 父传子&#xff1a;defineProps的TS写法 // 父组件&#xff1a;和 vue2 一样正常传值 <template><div class"login-page"><cp-nav-bar title"登录" right-text"注册"></cp-nav-bar></div> &…...

RK3566添加湿度传感器以及浅析hal层

RK3566添加一款温湿度传感器gxht3x.挂在i2c总线下。驱动部分就不多做解析。大致流程硬件接好i2c线以及vcc gnd。后看数据手册。初始化寄存器&#xff0c;然后要读数据的话读那个寄存器&#xff0c;读出来的数据要做一个转化,然后实现open read write ioctl函数就行了。本文主要…...

看了这份Java高级笔试宝典覆盖近3年Java笔试中98%高频知识点,反打面试官

首先声明&#xff1a; 本书覆盖了近3年程序员面试笔试中超过98%Java高频知识点&#xff0c;当你细细品读完本书后&#xff0c;面试都是小问题。 一书在手/工作不愁 记住重点&#xff0c;考试要考 前言 程序员求职始终是当前社会的一个热点&#xff0c;而市面上有很多关于程…...

从0到1搭建大数据平台之监控

大家好&#xff0c;我是脚丫先生 (o^^o) 大数据平台设计中&#xff0c;监控系统尤为重要。 它时刻关乎大数据开发人员的幸福感。 试想如果半夜三更&#xff0c;被电话吵醒解决集群故障问题&#xff0c;那是多么的痛苦&#xff01;&#xff01;&#xff01; 但是不加班是不可…...

采购评标管理过程是怎样的?有哪些评标标准?

采购活动的评标是检查和比较投标的有组织的过程&#xff0c;以选择最佳报价&#xff0c;努力获得实现企业目标所需的货物、工程和服务。 评标是由一个被称为评标小组的机构负责。这个小组如何称呼&#xff0c;取决于企业的情况。同义词有报价审查小组、投标审查委员会或投标审…...

《Vue+Spring Boot前后端分离开发实战》专著累计发行上万册

杰哥的学术专著《VueSpring Boot前后端分离开发实战》由清华大学出版社于2021年3月首次出版发行&#xff0c;虽受疫情影响但热度不减&#xff0c;受到业界读者的热捧&#xff0c;截至今日加印5次&#xff0c;累计发行12000册&#xff0c;引领读者开发前后端分离项目&#xff0c…...

类与类之间的关系有哪几种?

文章目录程序设计要素1.可读性2.健壮性3.优化4.复用性5.可扩展性设计类的关系遵循的原则1、 高内聚低耦合2、面向对象开发中 “针对接口编程优于针对实现编程”&#xff0c;”组合优于继承” 的总体设计类与类之间的关系&#xff08;即事物关系&#xff09; A is-a B 泛化&…...

LeetCode 606.根据二叉树创建字符串,102.二叉树的层序遍历和牛客 二叉搜索树与双向链表

文章目录1. 根据二叉树创建字符串2. 二叉树的层序遍历3. 二叉搜索树与双向链表1. 根据二叉树创建字符串 难度 简单 题目链接 解题思路&#xff1a; 这里的意思就是&#xff1a;用前序遍历遍历这颗树。然后左子树和右子树分别在一个括号里。括号里的规则是&#xff1a; 1.左右都…...

02-18 周六 图解机器学习之SMV 第五章5-2

02-18 周六 图解机器学习之SMV 第五章5-2时间版本修改人描述2023年2月18日11:47:18V0.1宋全恒新建文档 环境 程序的基本环境&#xff0c;是使用了jupyter&#xff0c;在容器中运行的。 简介 本程序主要演示支持向量的获取&#xff0c;支持向量是距离超平面最近的点组成的。程序…...

Spring Boot系列--创建第一个Spring Boot项目

1.项目搭建 在IDEA中新建项目&#xff0c;选择Spring Initializr。 填写项目信息&#xff1a; 选择版本和Spring Web依赖&#xff1a; Spring Web插件能为项目集成Tomcat、配置dispatcherServlet和xml文件。此处选择的版本若为3.0.2的话会出现如下错误&#xff1a; java: …...

手把手教你用React Hook和TypeScript从零实现虚拟滚动列表组件

前言 k8s 全称 kubernetes&#xff0c;这个名字大家应该都不陌生&#xff0c;k8s是为容器服务而生的一个可移植容器的编排管理工具&#xff0c;集应用的部署和运维&#xff0c;负载均衡&#xff0c;服务发现和扩容&#xff0c;版本回滚于一身&#xff0c;越来越多的公司正在拥…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...