Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【gtest】 C++ 的测试框架之使用 gtest 编写单元测试

【gtest】 C++ 的测试框架之使用 gtest 编写单元测试

作者头像
SarPro
发布于 2024-06-15 04:32:38
发布于 2024-06-15 04:32:38
2.8K00
代码可运行
举报
文章被收录于专栏:【计网】Cisco【计网】Cisco
运行总次数:0
代码可运行

🌊前言

gtest 是 Google 开发的一个用于 C++ 的测试框架,广泛应用于编写和运行单元测试,并且支持任何类型的测试,而不仅仅是单元测试。

本教程分成以下部分:

  • GoogleTest 入门(GoogleTest Primer - 教你如何使用 GoogleTest 编写简单的测试。如果你是 GoogleTest 新手,请先阅读此部分。
  • GoogleTest 高级教程(GoogleTest Advanced - 当你完成入门教程并想充分利用 GoogleTest 时,请阅读此部分。
  • GoogleTest 示例(GoogleTest Samples - 介绍一些 GoogleTest 示例。
  • GoogleTest 常见问题解答(GoogleTest FAQ- 有问题吗?想要一些提示?请先查看这里。
  • 模拟初学者指南 (Mocking for Dummies- 教你如何创建模拟对象并在测试中使用它们。
  • 模拟秘籍 (Mocking Cookbook - 包含常见模拟用例的技巧和方法。
  • 模拟速查表 (Mocking Cheat Sheet - 用于匹配器、动作、不变量等的便捷参考。
  • 模拟常见问题解答(Mocking FAQ - 包含一些特定于模拟的常见问题的答案。

注意:

  • 本教程使用 cmake 启动并运行 GoogleTest:需提前安装 CMake。
  • 术语:测试(Test)、测试用例(Test Case)和测试套件(Test Suite)。

🌊使用 cmake 启动并运行 gtest

🌍1. 设置项目

CMake 使用 CMakeLists.txt 来配置项目的构建系统【使用该文件设置项目,并声明对 gtest 的依赖】

首先,创建一个项目的目录:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
mkdir my_project && cd my_project

接下来,将创建 CMakeLists.txt 文件并声明对 GoogleTest 的依赖。

在项目目录(my_project)中,创建一个名为 CMakeLists.txt 的文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vim CMakeLists.txt

其内容如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cmake_minimum_required(VERSION 3.14)
project(my_project)

# 设置 C++ 标准为 C++14
set(CMAKE_CXX_STANDARD 14)
# 强制要求编译器支持所选的 C++ 标准
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 包含 FetchContent 模块,用于从外部资源获取依赖项
include(FetchContent)
FetchContent_Declare(
  googletest
  URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)
# 对于 Windows 系统:防止覆盖父项目的编译器/链接器设置
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# 使得 GoogleTest 可用
FetchContent_MakeAvailable(googletest)

这个文件中包括了以下部分:

  1. cmake_minimum_required(VERSION 3.14):指定了 CMake 的最低版本要求。
  2. project(my_project):定义了项目的名称。
  3. set(CMAKE_CXX_STANDARD 14)set(CMAKE_CXX_STANDARD_REQUIRED ON):设置了 C++ 标准为 C++14,且要求编译器支持此标准。
  4. include(FetchContent):包含了 CMake 的 FetchContent 模块,用于从外部资源(如 GitHub)获取依赖项。
  5. FetchContent_Declare(googletest URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip):声明了对 GoogleTest 的依赖,指定了下载地址。
  6. set(gtest_force_shared_crt ON CACHE BOOL "" FORCE):对于 Windows 系统,防止覆盖父项目的编译器/链接器设置。
  7. FetchContent_MakeAvailable(googletest):获取并使 GoogleTest 可用。

🌍2. 创建并运行二进制文件

将 gtest 声明为一个依赖项后,你就可以在自己的项目中使用 GoogleTest 代码。

举例来说,在 my_project 目录中创建一个名为 hello_test.cc 的文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
vim hello_test.cc 

内容如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <gtest/gtest.h>

// 展示一些基本断言。
TEST(HelloTest, BasicAssertions) {
  // 期望两个字符串不相等。
  EXPECT_STRNE("hello", "world");
  // 期望相等。
  EXPECT_EQ(7 * 6, 42);
}

要构建代码,需要将以下内容添加到你的 CMakeLists.txt 文件末尾:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# 启用测试
enable_testing()

# 声明要测试的可执行文件
add_executable(
  hello_test
  hello_test.cc
)
# 链接 GoogleTest 主要库
target_link_libraries(
  hello_test
  GTest::gtest_main
)

# 包含 GoogleTest 模块
include(GoogleTest)
# 使用 gtest_discover_tests 函数来自动发现并添加测试
gtest_discover_tests(hello_test)

上述配置启用了 CMake 中的测试,声明了要构建的 C++ 测试二进制文件(hello_test),并将其链接到 GoogleTest(gtest_main)。 最后两行启用了 CMake 的测试运行器,使用 GoogleTest 的 CMake 模块来发现包含在二进制文件中的测试。

现在你可以依据下面指令构建和运行你的测试:

1.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cmake -S . -B build
  • 告诉 CMake 在当前目录(-S .)中查找 CMakeLists.txt 文件,并在指定的构建目录 build 中生成构建系统文件(-B build)。

2.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cmake --build build
  • cmake 是调用 CMake 工具的命令。
  • --build 是用于告诉 CMake 执行构建操作的选项。
  • build 是构建目录的路径,指定了 CMake 在build 路径下执行构建操作。

3.

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
cd build && ctest
  • cd build 进入构建目录。
  • ctest 会查找构建目录中的测试,并执行它们。

显示如下内容:

恭喜!你成功地构建并运行了一个使用 GoogleTest 的测试二进制文件。

🌊1. gtest 入门

使用 gtest 时,首先要会编写断言(assertions),这些是检查条件是否为真的语句。

一个断言的结果可以是成功、非致命失败致命失败【如果发生致命失败,它会中止当前函数;否则程序会正常继续执行】

测试使用断言来验证被测试代码的行为。如果一个测试崩溃或有一个失败的断言,那么它失败;否则它成功。

  • 一个测试套件(test suite)包含一个或多个测试(test)。应该将你的测试(test)分组到反映被测代码结构的测试套件(test suite)中。
  • 一个测试程序可以包含多个测试套件(test suite)。

接下来,我们将解释如何编写一个测试程序,从单个断言级别开始,逐步构建到测试和测试套件。


🌍1.1 断言(assertions)

断言(assertions)是类似函数调用的宏。你可以通过对其行为进行断言来测试一个类或函数。当一个断言失败时,gtest 会打印断言的源文件和行号位置,以及一个失败消息。你还可以提供一个自定义的失败消息,它将附加到 gtest 的消息中。

这些断言成对出现,测试相同的事物,但对当前函数有不同的影响。

  • ASSERT_* 版本在失败时会生成致命失败,并中止当前函数。
  • EXPECT_* 版本生成非致命失败,不会中止当前函数。

通常情况下,优先使用 EXPECT_*,因为它们允许在一个测试中报告多个失败。然而,如果在相关断言失败时继续执行不合理,则应该使用 ASSERT_*。 由于失败的 ASSERT_* 会立即返回当前函数,可能会跳过其后的清理代码,从而可能导致空间泄漏。根据泄漏的性质,如果除了断言错误外还出现堆检查器错误。 要提供自定义的失败消息,只需使用 << 运算符或一系列此类运算符将其流式传递到宏中。

【示例】使用 ASSERT_EQ 和 EXPECT_EQ 宏来验证值的相等性:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ASSERT_EQ(x.size(), y.size()) << "Vectors x and y are of unequal length";

for (int i = 0; i < x.size(); ++i) {
  EXPECT_EQ(x[i], y[i]) << "Vectors x and y differ at index " << i;
}

任何可以流式传输到 ostream 的内容都可以流式传输到断言宏中 - 特别是 C 字符串字符串对象。如果将宽字符串(wchar_t*、 TCHAR*在 Windows 的UNICODE 模式下,或者 std::wstring)流式传输到断言中,则在打印时会被转换为 UTF-8 编码。

gtest 提供了一系列断言,用于以各种方式验证代码的行为。可以检查布尔条件,基于关系运算符比较值,验证字符串值、浮点值等等。甚至还有一些断言可以通过提供自定义谓词来验证更复杂的状态。


🌍1.2 简单测试

  • 使用 TEST() 宏来定义和命名一个测试函数。这些是普通的 C++ 函数,不返回任何值。
  • 在这个函数中,除了你想包含的有效的 C++ 语句,使用各种 gtest 断言来检查值。
  • 测试结果由断言确定;如果测试中的任何断言失败(无论是致命还是非致命),或者测试崩溃,整个测试都将失败。否则,它成功。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
TEST(TestSuiteName, TestName) {
  ... test body ...
}

TEST() 宏的第一个参数是测试套件(test suite)的名称,第二个参数是测试套件内的测试名称。两个名称都必须是有效的 C++ 标识符,并且不能包含下划线【测试的全名=其所属的测试套件+其单独的名称组成。来自不同测试套件的测试可以有相同的单独名称】

【示例】以一个简单的整数函数为例

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int Factorial(int n);  // 返回 n 的阶乘

此函数的测试套件可能如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 测试 0 的阶乘
TEST(FactorialTest, HandlesZeroInput) {
  // 期望 Factorial(0) 的结果是 1
  EXPECT_EQ(Factorial(0), 1);
}

// 测试正数的阶乘
TEST(FactorialTest, HandlesPositiveInput) {
  // 期望 Factorial(1) 的结果是 1
  EXPECT_EQ(Factorial(1), 1);
  // 期望 Factorial(2) 的结果是 2
  EXPECT_EQ(Factorial(2), 2);
  // 期望 Factorial(3) 的结果是 6
  EXPECT_EQ(Factorial(3), 6);
  // 期望 Factorial(8) 的结果是 40320
  EXPECT_EQ(Factorial(8), 40320);
}

GoogleTest 按测试套件分组测试结果,因此逻辑上相关的测试应在同一个测试套件中;换句话说,它们的 TEST() 的第一个参数应该相同。

在上面的示例中,我们有两个测试,HandlesZeroInput 和 HandlesPositiveInput,它们属于同一个测试套件 FactorialTest。

在命名你的测试套件和测试时,应该遵循与命名函数和类相同的约定。


🌍1.3 测试夹具:为多个测试使用相同的数据配置

Test Fixture(测试夹具)是指在测试运行前后,需要被执行的代码片段。

如果你发现自己在编写两个或更多操作相似数据的测试,可以使用测试夹具。这样可以为多个不同的测试重复使用相同的对象配置。

创建夹具的步骤:

  1. testing::Test 派生一个类。在类体开始处使用 protected:,因为我们希望从子类访问夹具成员。
  2. 在类中声明你需要使用的任何对象。
  3. 如果需要,编写一个默认构造函数或 SetUp() 函数,为每个测试准备对象。 一个常见的错误是将 SetUp() 拼写为小写的 Setup() - 在 C++11 中使用 override 确保拼写正确。
  4. 如果需要,编写一个析构函数或 TearDown() 函数来释放你在 SetUp() 中分配的任何资源。
  5. 如果需要,为你的测试定义共享的子程序。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 定义夹具类
class MyTestFixture : public testing::Test {
protected:
    // 在这里声明你的对象
    int* myObject;

    // 如果需要,编写构造函数或 SetUp() 函数
    void SetUp() override {
        myObject = new int(42); // 示例初始化
    }

    // 如果需要,编写析构函数或 TearDown() 函数
    void TearDown() override {
        delete myObject;
    }
};

// 使用 TEST_F() 进行测试
TEST_F(MyTestFixture, Test1) {
    // 可以在这里访问 myObject
    EXPECT_EQ(*myObject, 42);
}

TEST_F(MyTestFixture, Test2) {
    // 也可以在这里访问 myObject
    EXPECT_NE(*myObject, 0);
}

使用夹具时,使用 TEST_F() 而不是 TEST(),因为它允许你访问测试夹具中的对象和子程序:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
TEST_F(TestFixtureClassName, TestName) {
  ... test body ...
}

本文参考GoogleTest 用户指南:GoogleTest User’s Guide | GoogleTest

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
gtest单元测试框架介绍及简单使用
Gtest是Google的一个开源框架,它主要用于写单元测试,检查真自己的程序是否符合预期行为。可在多个平台上使用(包括Linux, Mac OS X, Windows, Cygwin和Symbian)。它提供了丰富的断言、致命和非致命失败判断,能进行值参数化测试、类型参数化测试、“死亡测试”。
杨永贞
2022/04/13
4.2K0
gtest单元测试框架介绍及简单使用
google软件测试之道_gtest测试框架
gtest 提供了一套优秀的 C++ 单元测试解决方案,简单易用,功能完善,非常适合在项目中使用以保证代码质量。
全栈程序员站长
2022/11/10
7890
google软件测试之道_gtest测试框架
Google 单元测试框架
到 github 拉取代码或者下载某个版本的 zip 包到本地目录,参考 gtest 中的 README.md 如何编译库和编译自己的代码,下面简单介绍下编译方法
orientlu
2018/09/13
2.2K0
(Android下使用)Google Test C++单元测试框架(一)
gtest是一个跨平台的(Liunx、Mac OS X、Windows、Cygwin、Windows CE and Symbian)C++单元测试框架,由google公司发布。gtest是为在不同平台上为编写C++测试而生成的。它提供了丰富的断言、致命和非致命判断、参数化、”死亡测试”等等。
李小白是一只喵
2020/04/24
2.9K0
(Android下使用)Google Test C++单元测试框架(一)
【GoogleTest】GoogleTest单元测试(1)快速上手
快速上手 GoogleTest是Google的一套用于编写 C++测试的框架,可以运行在多个平台上(包括Linux、MacOS X、Windows、Cygwin等)。基于xUnit架构,支持很多好用的特性,包括自动识别测试、丰富的断言、断言自定义、死亡测试、非终止的失败、生成XML报告等等。 以下简称GTest。 ---- GTest的优点 好的测试应包括如下特点。 测试应该是独立的、可重复的。一个测试的结果不应该作为另一个测试的前提。 GTest中每个测试运行在独立的对象中。如果某个测试
半生瓜的blog
2023/05/13
7910
【GoogleTest】GoogleTest单元测试(1)快速上手
单测:Google Test框架
Google Test是一个流行的C++单元测试框架,它提供了丰富的断言和测试工具,用于编写和运行单元测试。基于流行的 xUnit 架构
lealc
2024/03/22
9450
单测:Google Test框架
gtest初识_tests strength
TEST()第一个参数是测试用例的名称,第二个参数是测试用例中的测试名称(有效的C++标识符,不应包含下划线)。 googletest按照测试用例对测试结果进行分组。
全栈程序员站长
2022/11/11
5060
gtest整理_softest
::testing::Bool() 会生成 true 和 false两种值,::testing::Combine 把 {true,false} 和 {1, 10} 这两个集合的值组合起来,相当于
全栈程序员站长
2022/09/27
1.6K0
C++ 项目之Googletest单元测试
Googletest - Google Testing and Mocking Framework
公众号guangcity
2019/09/20
4.2K0
GTest 总结_gtest单元测试
Google C++单元测试框架(简称Gtest),可在多个平台上使用(包括Linux, Mac OS X, Windows, Cygwin和Symbian),它提供了丰富的断言、致命和非致命失败判断,能进行值参数化测试、类型参数化测试、“死亡测试”。
全栈程序员站长
2022/11/11
2K0
GTest 总结_gtest单元测试
【C++】开源:单元测试框架gtest配置使用
项目Github地址:https://github.com/google/googletest.git
DevFrank
2024/07/24
3280
Google Test(GTest)使用方法和源码解析——概况
        GTest是很多开源工程的测试框架。虽然介绍它的博文非常多,但是我觉得可以深入到源码层来解析它的实现原理以及使用方法。这样我们不仅可以在开源工程中学习到实用知识,还能学习到一些思想和技巧。我觉得有时候思想和技巧是更重要的。(转载请指明出于breaksoftware的csdn博客)
方亮
2019/01/16
4.7K0
C++语言的单元测试与代码覆盖率
直接交付没有经过测试的代码是不太好的,因为这很可能会浪费整个团队的时间,在一些原本早期就可以发现的问题上。而单元测试,就是发现问题一个很重要的环节。
顾翔
2019/12/11
3.3K0
C++语言的单元测试与代码覆盖率
GTest的安装与使用
顾翔老师开发的bugreport2script开源了,希望大家多提建议。文件在https://github.com/xianggu625/bug2testscript,
顾翔
2019/12/12
2.4K0
GTest的安装与使用
CICD实战——服务自动测试
随着微服务、容器、云计算的发展,近些年 DevOps、CI/CD 等概念越来越多地映入大家的眼帘。许多开发团队都希望应用这些理念来提高软件质量和开发效率,工欲善其事必先利其器,什么样的工具才能够满足开发者的需求?TARS 作为一套优秀的开源微服务开发运营一体化平台,拥有多语言、高性能、敏捷研发、高可用等特点。那么 TARS 是否能够完美支持 DevOps 理念呢?在上一篇文章中,我们了解了如何将开源 CI 工具 Jenkins 与 TARS 集成实现 TARS 服务的自动化构建与部署。而软件测试是软件开发过程中必不可少的一步,本文将在上一篇文章的基础上,以一次完整的实践来展示如何通过 Jenkins 与 TARS 集成实现 TARS 服务的自动化单元测试。
TARS基金会
2020/09/30
2K0
CICD实战——服务自动测试
(Android下使用)Google Test C++单元测试框架(二)
TEST() and TEST_F() implicitly register their tests with googletest. So, unlike with many other C++ testing frameworks, you don't have to re-list all your defined tests in order to run them.
李小白是一只喵
2020/04/24
1.9K0
(Android下使用)Google Test C++单元测试框架(二)
如何用googletest写单元测试
googletest是一个用来写C++单元测试的框架,它是跨平台的,可应用在windows、Linux、Mac等OS平台上。下面,我来说明如何使用最新的1.6版本gtest写自己的单元测试。
陶辉
2019/06/21
6.8K0
如何用googletest写单元测试
【gTest】gtest简介及简单使用
gtest是一个跨平台(Liunx、Mac OS X、Windows、Cygwin、Windows CE and Symbian)的C++测试框架,有google公司发布。gtest测试框架是在不同平台上为编写C++测试而生成的。
全栈程序员站长
2022/11/11
2.2K0
gtest框架_软件测试框架
以上命令会将gtest编译好,并将静态链接库放在/usr/local/lib 目录下: zhouhao@ubuntu:/usr/local/lib$ ls libgmock.a libgtest.a pkgconfig python3.6 libgmock_main.a libgtest_main.a python2.7
全栈程序员站长
2022/11/10
2.9K0
gtest_gtest测试静态函数
编译: 假设源代码为sample.h和sample.cpp,测试代码为test.cpp
全栈程序员站长
2022/11/11
1.1K0
相关推荐
gtest单元测试框架介绍及简单使用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验