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

【GTest 】GTest 详解以及安装教程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

 

一、GTest 是什么?单元测试的 “标准化武器”

二、GTest 核心概念:从 “测试用例” 到 “测试套件”

1. 测试用例(Test Case)

2. 测试套件(Test Suite)

3. 断言(Assertion)

三、GTest 安装:两种方式,按需选择

方式 1:系统命令直接安装(以 Ubuntu 为例)

方式 2:源码编译安装(适合定制或无包管理器场景)

步骤 1:下载源码

步骤 2:编译安装

验证安装是否成功

四、GTest 实战:从 “单测入门” 到 “工程化测试”

示例 1:基础断言与测试用例组织

示例 2:参数化测试(减少重复代码)

示例 3:事件机制(测试环境的初始化与清理)

五、GTest 工程化实践:那些你该知道的细节

1. 致命断言 vs 非致命断言

2. 死亡测试(验证程序异常退出)

3. 与构建系统的集成

 


一、GTest 是什么?单元测试的 “标准化武器”

GTest 是谷歌推出的跨平台 C++ 单元测试框架,它的诞生就是为了解决 “不同平台下 C++ 单元测试编写繁琐” 的痛点。无论是 Windows、Linux 还是 macOS,GTest 都能无缝运行。

它到底强在哪?核心优势一目了然:

  • 断言丰富:提供几十种断言宏(如ASSERT_EQ判断相等、ASSERT_TRUE判断真),能精准表达测试逻辑。
  • 场景覆盖全:支持致命断言(断言失败则测试用例直接终止)、非致命断言(断言失败不终止,继续执行后续逻辑),还能做参数化测试、死亡测试(验证程序异常退出场景)。
  • 结构清晰:通过 “测试套件 - 测试用例” 的层级结构,让大量测试用例也能组织得井井有条。
  • 自动化程度高:只需写好测试用例,GTest 能自动发现、执行并生成直观的测试报告。

二、GTest 核心概念:从 “测试用例” 到 “测试套件”

在动手写测试前,先理清 GTest 的核心概念,能让你少走很多弯路。

1. 测试用例(Test Case)

一个 “测试用例” 对应一个最小的测试单元,用来验证某一个具体功能或逻辑点。比如测试 “绝对值函数是否正确” 就是一个测试用例。

2. 测试套件(Test Suite)

多个相关的测试用例可以组成一个 “测试套件”。比如 “数学工具类” 这个套件,可以包含 “绝对值函数测试”“求和函数测试” 等多个用例。

3. 断言(Assertion)

断言是 GTest 的 “灵魂”,它用来判断代码运行结果是否符合预期。比如ASSERT_EQ(a, b)表示 “断言 a 和 b 相等”,如果不相等,测试就会失败。

三、GTest 安装:两种方式,按需选择

GTest 的安装很灵活,你可以用系统包管理器快速装,也可以从源码编译定制,我们逐个说明。

方式 1:系统命令直接安装(以 Ubuntu 为例)

这种方式最省心,适合快速上手:

 

sudo apt-get update
sudo apt-get install libgtest-dev

安装完成后,系统会把 GTest 的头文件和库文件放到标准路径,编译测试程序时只需链接 GTest 库即可。

方式 2:源码编译安装(适合定制或无包管理器场景)

如果你的系统没有现成包,或者需要指定版本,源码编译是更灵活的选择。

步骤 1:下载源码

GTest 的源码托管在 GitHub 上,执行以下命令下载:

 

git clone https://github.com/google/googletest.git
cd googletest/
步骤 2:编译安装

GTest 使用 CMake 构建,执行以下命令编译安装:

 

mkdir build
cd build/
cmake ..
make
sudo make install

安装完成后,头文件默认在/usr/local/include/gtest,库文件在/usr/local/lib。编译测试程序时,链接-lgtest -lgtest_main -pthread即可(-pthread是因为 GTest 依赖多线程)。

验证安装是否成功

写一个简单的测试程序,能正常编译运行就说明安装成功了。比如下面这个 “绝对值函数测试”:

 

#include <gtest/gtest.h>// 要测试的绝对值函数
int abs(int x) {return x > 0 ? x : -x;
}// 测试套件:abs_test;测试用例:test1
TEST(abs_test, test1) {ASSERT_TRUE(abs(1) == 1) << "abs(1) 应该等于 1";ASSERT_TRUE(abs(-1) == 1) << "abs(-1) 应该等于 1";ASSERT_FALSE(abs(-2) == -2) << "abs(-2) 不应该等于 -2";ASSERT_EQ(abs(1), abs(-1)); // 判断相等ASSERT_NE(abs(-1), 0);      // 判断不相等ASSERT_LT(abs(-1), 2);      // 判断小于ASSERT_GT(abs(-1), 0);      // 判断大于ASSERT_LE(abs(-1), 2);      // 判断小于等于ASSERT_GE(abs(-1), 0);      // 判断大于等于
}int main(int argc, char** argv) {// 初始化GTest框架testing::InitGoogleTest(&argc, argv);// 运行所有测试用例return RUN_ALL_TESTS();
}

编译并运行:

 

g++ gtest_demo.cpp -o gtest_demo -lgtest -lgtest_main -pthread
./gtest_demo

如果输出类似 “[==========] Running 1 test from 1 test suite.” 的测试报告,说明 GTest 安装和运行都没问题。

四、GTest 实战:从 “单测入门” 到 “工程化测试”

光说不练假把式,我们通过几个场景,看看 GTest 在实际开发中怎么用。

示例 1:基础断言与测试用例组织

我们以 “字符串工具类” 为例,测试它的 “拼接” 和 “长度计算” 功能:

 

#include <gtest/gtest.h>
#include <string>// 要测试的字符串工具类
class StringUtil {
public:static std::string concat(const std::string& a, const std::string& b) {return a + b;}static size_t length(const std::string& s) {return s.length();}
};// 测试套件:StringUtilTest
TEST(StringUtilTest, ConcatTest) {std::string res = StringUtil::concat("hello", "world");ASSERT_EQ(res, "helloworld");ASSERT_EQ(StringUtil::length(res), 10);
}TEST(StringUtilTest, LengthTest) {ASSERT_EQ(StringUtil::length(""), 0);ASSERT_EQ(StringUtil::length("gtest"), 5);
}int main(int argc, char** argv) {testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();
}

这个例子中,我们把两个相关的测试用例(ConcatTestLengthTest)放到StringUtilTest套件下,结构非常清晰。

示例 2:参数化测试(减少重复代码)

如果要测试 “多个输入下的同一逻辑”,参数化测试能帮你少写很多重复代码。比如测试 “加法函数” 在不同输入下的结果:

 

#include <gtest/gtest.h>// 要测试的加法函数
int add(int a, int b) {return a + b;
}// 定义参数化测试的参数类型
class AddParamTest : public testing::TestWithParam<std::tuple<int, int, int>> {
};// 参数化测试用例
TEST_P(AddParamTest, Test) {int a = std::get<0>(GetParam());int b = std::get<1>(GetParam());int expected = std::get<2>(GetParam());ASSERT_EQ(add(a, b), expected);
}// 注册参数
INSTANTIATE_TEST_SUITE_P(AddTest,AddParamTest,testing::Values(std::make_tuple(1, 2, 3),std::make_tuple(0, 0, 0),std::make_tuple(-1, 2, 1),std::make_tuple(100, 200, 300))
);int main(int argc, char** argv) {testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();
}

这样,GTest 会自动遍历所有参数,执行测试用例,大大减少了代码冗余。

示例 3:事件机制(测试环境的初始化与清理)

在实际测试中,经常需要 “测试前准备数据,测试后清理数据”,GTest 的事件机制就能帮你实现这个需求。

GTest 的事件分为三个层级:

  • 全局事件:针对整个测试程序,在所有测试开始前执行一次初始化,所有测试结束后执行一次清理。
  • 测试套件事件:针对某个测试套件,在该套件的所有用例开始前初始化,所有用例结束后清理。
  • 测试用例事件:针对单个测试用例,在用例开始前初始化,用例结束后清理。

我们以 “全局事件” 为例,实现一个 “测试前加载配置,测试后释放配置” 的逻辑:

 

#include <gtest/gtest.h>
#include <unordered_map>
#include <string>// 全局配置字典
std::unordered_map<std::string, std::string> g_config;// 自定义环境类,继承自testing::Environment
class GlobalEnv : public testing::Environment {
public:// 测试程序启动前执行void SetUp() override {std::cout << "全局初始化:加载配置..." << std::endl;g_config["db_host"] = "127.0.0.1";g_config["db_port"] = "3306";}// 测试程序结束后执行void TearDown() override {std::cout << "全局清理:释放配置..." << std::endl;g_config.clear();}
};// 测试用例:验证配置是否加载
TEST(ConfigTest, LoadTest) {ASSERT_EQ(g_config["db_host"], "127.0.0.1");ASSERT_EQ(g_config["db_port"], "3306");
}int main(int argc, char** argv) {// 注册全局事件testing::AddGlobalTestEnvironment(new GlobalEnv());testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();
}

运行这个程序,你会看到 “加载配置” 在所有测试前执行,“释放配置” 在所有测试后执行,完美实现了测试环境的管理。

五、GTest 工程化实践:那些你该知道的细节

1. 致命断言 vs 非致命断言

  • 致命断言:以ASSERT_xxx开头(如ASSERT_EQ),断言失败时当前测试用例直接终止
  • 非致命断言:以EXPECT_xxx开头(如EXPECT_EQ),断言失败时当前测试用例继续执行后续逻辑
  • 选择原则:如果一个断言失败后,后续逻辑无意义,用ASSERT_xxx;否则用EXPECT_xxx

2. 死亡测试(验证程序异常退出)

如果要测试 “程序在异常输入下是否会按预期退出”,可以用死亡测试:

 

#include <gtest/gtest.h>// 一个会崩溃的函数
void crash() {int* p = nullptr;*p = 10; // 解引用空指针,程序崩溃
}// 死亡测试用例
TEST(DeathTest, CrashTest) {// 断言程序执行crash()时会崩溃(退出码非0)ASSERT_DEATH(crash(), "");
}

3. 与构建系统的集成

在实际项目中,建议把 GTest 测试代码和业务代码分开编译。比如用 CMake 的话,可以这样配置:

 

# 查找GTest库
find_package(GTest REQUIRED)# 测试可执行文件
add_executable(test_my_lib test_my_lib.cpp)
# 链接GTest和业务库
target_link_libraries(test_my_lib PRIVATE my_lib GTest::GTest GTest::Main)# 添加测试目标
add_test(NAME test_my_lib COMMAND test_my_lib)

 

http://www.dtcms.com/a/530254.html

相关文章:

  • 网站建设的实践报告怎么查询自己的二建信息
  • 高端品牌网站建设案例网站开发方向学啥
  • 绿色做环保网站的好处主机如何做服务器建网站
  • 宜宾网站建设宜宾wordpress用户筛选
  • 华为自助建站做钓鱼网站要具备什么
  • 企业营销型网站制作多少钱杭州cms建站模板
  • 怎么做简单地网站网站的备案流程
  • 网站开发能进入无形资产吗太原百度做网站多少钱
  • 【gflags 】gflags 详解以及安装教程
  • 网站系统 建设和软件岗位职责微信小程序一起生活怎么注册
  • 网站 vps网站开发的流程
  • 做区块链网站的公司郑州网站开发定制
  • 网店网站建设哪家ppt模板免费背景
  • 医院网站内链优化百度一下你就知道官网网页
  • 论坛型网站 建站dede网站前台没有图片
  • 宿迁网站建设宿迁网站设计开发收费标准
  • Java—多态
  • 博客网站搭建中工信融网站建设
  • 织梦网站维护工商网企业信息查询系统营业执照
  • 做企业网站的研究现状祥云网站建设公司 概况
  • 现在的网站使用frameset做吗天津建设工程招标网
  • 20252803-动态库的使用-openssl
  • 网站建设平台哪个好推广产品的方式有哪些
  • 制作网站的花多少钱一级a做爰片2017免费网站
  • 怎样创建网站教程网站主机多少钱
  • 湘潭网站建设优选磐石网络网页翻译网站
  • 网站建设企业 熊账号如何制作wordpress主题
  • 27_AI智能体提示词工程之动态加载情感分析提示词模板的最佳实践
  • Windows 中启动 ms office 报错0xc0000142
  • 红河学院网站建设北京造价信息网官网