吐鲁番市网站建设_网站建设公司_阿里云_seo优化
2025/12/27 14:16:19 网站建设 项目流程

文章目录

  • 安装gtest开发包
  • 进入编译目录
  • 创建构建目录
  • 编译生成静态库
  • 复制库文件到系统库目录
  • 克隆gtest源码
  • 创建构建目录(采用体外构建,避免污染源码)
  • 配置编译选项(可指定安装路径,如-DCMAKE_INSTALL_PREFIX=/usr/local)
  • 编译(-j指定线程数,加速编译)
  • 安装到系统目录
  • 编译测试程序,链接gtest和pthread库(gtest依赖线程库)
  • 运行测试程序
  • 只执行测试套件为CalculatorFixture的所有测试用例
  • 只执行测试用例名称包含Add的测试
  • 排除某个测试用例
  • 编译测试程序
  • 运行测试

在软件开发过程中,单元测试是保障代码质量、提升开发效率的关键环节。Google Test(简称gtest)作为一款开源的C++单元测试框架,凭借其强大的功能、简洁的API设计和良好的跨平台特性,成为了C++开发者的首选测试工具之一。本文将从gtest的基本介绍、安装配置、核心概念、常用API到实战案例,全方位讲解gtest的使用方法,帮助开发者快速上手并应用于实际项目。

一、gtest简介

gtest是由Google开发的开源C++单元测试框架,遵循BSD开源协议,支持Linux、Windows、Mac等多种操作系统,可与CMake、Visual Studio、GCC等主流开发工具和编译环境无缝集成。其核心优势包括:

  • 丰富的断言机制:提供了大量针对布尔值、数值、字符串、容器等类型的断言宏,支持成功/失败断言、致命/非致命断言,满足不同场景的测试需求。

  • 灵活的测试组织方式:通过测试套件(Test Suite)和测试用例(Test Case)的层级结构,清晰组织测试代码;支持测试过滤、参数化测试、死亡测试等高级功能。

  • 完善的报告输出:可生成详细的测试报告,包含测试用例执行结果、失败原因、执行时间等信息,支持文本、XML等多种输出格式,便于集成到CI/CD流程。

  • 轻量级与可扩展性:核心代码简洁,依赖少,易于编译和部署;同时支持自定义断言、测试监听器等扩展机制,适配复杂项目的测试需求。

二、gtest安装与配置

gtest的安装配置方式主要分为源码编译安装和包管理器安装,以下分别介绍Linux(Ubuntu)和Windows(Visual Studio)环境下的配置方法。

2.1 Linux环境(Ubuntu)

2.1.1 包管理器安装(推荐,适用于简单需求)

Ubuntu系统可通过apt-get直接安装预编译的gtest包,命令如下:

安装gtest开发包

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

注意:libgtest-dev仅安装源码和头文件,并未自动编译生成库文件,需手动编译:

进入编译目录

cd /usr/src/gtest

创建构建目录

sudo mkdir build && cd build

编译生成静态库

sudo cmake …
sudo make

复制库文件到系统库目录

sudo cp libgtest.a libgtest_main.a /usr/lib

2.1.2 源码编译安装(适用于需要最新版本或自定义配置)

从GitHub获取最新源码并编译安装:

克隆gtest源码

git clone https://github.com/google/googletest.git
cd googletest

创建构建目录(采用体外构建,避免污染源码)

mkdir build && cd build

配置编译选项(可指定安装路径,如-DCMAKE_INSTALL_PREFIX=/usr/local)

cmake … -DCMAKE_BUILD_TYPE=Release

编译(-j指定线程数,加速编译)

make -j4

安装到系统目录

sudo make install

2.2 Windows环境(Visual Studio 2022)

2.2.1 源码编译配置

  1. 从GitHub下载gtest源码,解压后进入源码目录。

  2. 使用CMake-GUI生成Visual Studio解决方案:

  • 点击「Browse Source」选择gtest源码根目录(含CMakeLists.txt)。

  • 点击「Browse Build」选择构建目录(如build-vs2022)。

  • 点击「Configure」,选择Visual Studio 2022和平台(x64/x86),点击「Finish」完成配置。

  • 点击「Generate」生成解决方案文件(.sln)。

  1. 打开生成的解决方案,编译「ALL_BUILD」项目,生成静态库(gtest.lib、gtest_main.lib)。

  2. 在自己的项目中配置:

  • 项目属性 → C/C++ → 常规 → 附加包含目录:添加gtest源码的include目录(如googletest/include)。

  • 项目属性 → 链接器 → 常规 → 附加库目录:添加gtest编译生成的库目录(如build-vs2022/lib/Release)。

  • 项目属性 → 链接器 → 输入 → 附加依赖项:添加gtest.lib和gtest_main.lib(Debug模式添加gtestd.lib、gtest_maind.lib)。

三、gtest核心概念

在使用gtest前,需理解其两个核心概念:测试套件(Test Suite)和测试用例(Test Case)。

  • 测试套件(Test Suite):一组相关的测试用例的集合,通常对应一个类或一个功能模块。在gtest中,通过TEST宏定义测试套件,宏的第一个参数为测试套件名称。

  • 测试用例(Test Case):测试套件中的单个测试单元,对应一个具体的功能点或逻辑分支。TEST宏的第二个参数为测试用例名称。

示例:

#include <gtest/gtest.h>

// 测试套件:Calculator(计算器模块)
// 测试用例:AddTest(加法功能测试)
TEST(Calculator, AddTest) {
// 断言:验证1+1是否等于2
EXPECT_EQ(1 + 1, 2);
}

// 测试用例:SubtractTest(减法功能测试)
TEST(Calculator, SubtractTest) {
EXPECT_EQ(3 - 1, 2);
}

此外,gtest还提供了测试夹具(Test Fixture)机制,用于处理多个测试用例的共享初始化和清理逻辑(如创建对象、打开文件、释放资源等),通过继承testing::Test类实现。

四、gtest常用断言

断言是gtest的核心功能,用于判断测试代码的执行结果是否符合预期。gtest将断言分为两类:

  • 致命断言(Fatal Assertion):若断言失败,当前测试用例立即终止,后续代码不再执行。宏名以ASSERT_开头,如ASSERT_EQ、ASSERT_TRUE。

  • 非致命断言(Non-Fatal Assertion):若断言失败,当前测试用例继续执行,仅记录失败信息。宏名以EXPECT_开头,如EXPECT_EQ、EXPECT_TRUE。

推荐优先使用非致命断言,以便在一次测试中发现多个问题。以下是常用断言分类整理:

4.1 布尔值断言

断言宏

说明

示例

ASSERT_TRUE(condition)

致命断言:condition为真

ASSERT_TRUE(1 > 0)

ASSERT_FALSE(condition)

致命断言:condition为假

ASSERT_FALSE(1 < 0)

EXPECT_TRUE(condition)

非致命断言:condition为真

EXPECT_TRUE(isEven(2))

EXPECT_FALSE(condition)

非致命断言:condition为假

EXPECT_FALSE(isEven(3))

4.2 数值比较断言

断言宏

说明

示例

ASSERT_EQ(a, b)

致命断言:a == b(EQ=Equal)

ASSERT_EQ(2+3, 5)

ASSERT_NE(a, b)

致命断言:a != b(NE=Not Equal)

ASSERT_NE(5, 6)

ASSERT_LT(a, b)

致命断言:a < b(LT=Less Than)

ASSERT_LT(3, 5)

ASSERT_LE(a, b)

致命断言:a <= b(LE=Less or Equal)

ASSERT_LE(4, 5)

ASSERT_GT(a, b)

致命断言:a > b(GT=Greater Than)

ASSERT_GT(6, 5)

ASSERT_GE(a, b)

致命断言:a >= b(GE=Greater or Equal)

ASSERT_GE(5, 5)

注:EXPECT_系列对应的宏(如EXPECT_EQ、EXPECT_NE)功能相同,仅为非致命断言。

4.3 字符串断言

断言宏

说明

示例

ASSERT_STREQ(s1, s2)

致命断言:C风格字符串s1 == s2(区分大小写)

ASSERT_STREQ(“hello”, “hello”)

ASSERT_STRNE(s1, s2)

致命断言:C风格字符串s1 != s2

ASSERT_STRNE(“hello”, “world”)

ASSERT_STRCASEEQ(s1, s2)

致命断言:C风格字符串s1 == s2(不区分大小写)

ASSERT_STRCASEEQ(“Hello”, “hello”)

EXPECT_STREQ(s1, s2)

非致命断言:C风格字符串s1 == s2

EXPECT_STREQ(getName(), “Alice”)

4.4 异常断言

用于验证函数是否抛出预期的异常:

#include

// 测试函数是否抛出std::invalid_argument异常
TEST(ExceptionTest, DivideByZero) {
auto divide = [](int a, int b) {
if (b == 0) {
throw std::invalid_argument(“divide by zero”);
}
return a / b;
};
// 断言:调用divide(5, 0)时抛出std::invalid_argument异常
ASSERT_THROW(divide(5, 0), std::invalid_argument);
// 断言:调用divide(6, 2)时不抛出异常
ASSERT_NO_THROW(divide(6, 2));
}

五、gtest进阶功能

5.0 测试环境与生命周期管理

gtest提供了三级测试环境的生命周期管理机制,通过重写不同的SetUp(初始化)和TearDown(清理)方法,可实现不同范围的资源管控。各环境的执行时机有明确区分,核心分为全局环境、局部环境和最小环境三类:

  • 全局环境(testing::Environment):作用于所有测试用例的整个生命周期。其中SetUp方法在所有测试用例(如test1)执行前仅执行一次,TearDown方法在所有测试用例(如test3)执行完成后仅执行一次,适用于全局资源的初始化(如数据库连接、配置加载)和清理。

  • 局部环境(testing::Test的静态方法):作用于某个测试夹具对应的测试套件生命周期。通过静态方法SetUpTestCase实现,在该夹具的第一个测试用例(如test_f 2-1)执行前仅执行一次;通过静态方法TearDownTestCase实现,在该夹具的最后一个测试用例(如test_f 2-3)执行完成后仅执行一次,适用于测试套件级别的共享资源管控(如创建测试数据表、初始化共享对象)。

  • 最小环境(testing::Test的成员方法):作用于单个测试用例的生命周期。即之前提到的SetUp和TearDown成员方法,其中SetUp在每个测试用例(如每个test_f)执行前执行一次,TearDown在每个测试用例执行后执行一次,适用于单个测试用例的资源初始化(如创建临时对象)和清理。

全局环境需通过testing::AddGlobalTestEnvironment方法注册才能生效;局部环境和最小环境则通过测试夹具类的重写实现,具体示例如下:

5.1 测试夹具(Test Fixture)

当多个测试用例需要共享初始化和清理逻辑时,使用测试夹具。步骤如下:

  1. 继承testing::Test类,在类中定义共享的成员变量和方法。

  2. 重写SetUp()方法(可选):每个测试用例执行前调用,用于初始化资源(如创建对象)。

  3. 重写TearDown()方法(可选):每个测试用例执行后调用,用于清理资源(如释放对象)。

  4. 使用TEST_F宏定义测试用例(F=Fixture),第一个参数为夹具类名。

示例:测试计算器类的多个方法,结合全局环境、局部环境和最小环境实现资源的分级管控:

#include <gtest/gtest.h>
#include

// 1. 全局环境类:继承testing::Environment
class GlobalEnv : public testing::Environment {
public:
// 全局初始化:所有测试用例执行前执行一次
void SetUp() override {
std::cout << “全局环境SetUp:执行所有测试前的初始化(如加载全局配置)” << std::endl;
}

// 全局清理:所有测试用例执行后执行一次 void TearDown() override { std::cout << "全局环境TearDown:执行所有测试后的清理(如释放全局资源)" << std::endl; }

};

// 待测试的计算器类
class Calculator {
public:
int Add(int a, int b) { return a + b; }
int Subtract(int a, int b) { return a - b; }
int Multiply(int a, int b) { return a * b; }
int Divide(int a, int b) {
if (b == 0) throw std::invalid_argument(“divide by zero”);
return a / b;
}
};

// 2. 测试夹具类(含局部环境和最小环境):继承testing::Test
class CalculatorFixture : public testing::Test {
protected:
// 共享的计算器对象(最小环境使用)
Calculator calc;

// 局部环境-初始化:当前夹具的第一个测试用例执行前执行一次 static void SetUpTestCase() { std::cout << "局部环境SetUpTestCase:CalculatorFixture测试套件执行前初始化(如创建共享测试数据)" << std::endl; } // 局部环境-清理:当前夹具的最后一个测试用例执行后执行一次 static void TearDownTestCase() { std::cout << "局部环境TearDownTestCase:CalculatorFixture测试套件执行后清理(如删除共享测试数据)" << std::endl; } // 最小环境-初始化:每个测试用例执行前执行一次 void SetUp() override { std::cout << "最小环境SetUp:单个测试用例执行前初始化(如重置计算器状态)" << std::endl; } // 最小环境-清理:每个测试用例执行后执行一次 void TearDown() override { std::cout << "最小环境TearDown:单个测试用例执行后清理(如释放测试用例专属资源)" << std::endl; }

};

// 注册全局环境(必须注册才能生效)
TEST(GlobalEnvTest, Register) {
testing::AddGlobalTestEnvironment(new GlobalEnv);
}

// 3. 测试夹具对应的测试用例(模拟test_f 2-1、2-2、2-3)
TEST_F(CalculatorFixture, AddTest) { // test_f 2-1
EXPECT_EQ(calc.Add(1, 2), 3);
EXPECT_EQ(calc.Add(-1, -2), -3);
}

TEST_F(CalculatorFixture, SubtractTest) { // test_f 2-2
EXPECT_EQ(calc.Subtract(5, 3), 2);
EXPECT_EQ(calc.Subtract(3, 5), -2);
}

TEST_F(CalculatorFixture, DivideTest) { // test_f 2-3
EXPECT_EQ(calc.Divide(6, 2), 3);
ASSERT_THROW(calc.Divide(5, 0), std::invalid_argument);
}

// 其他独立测试用例(模拟test1、test3)
TEST(OtherTest, Test1) { // test1
std::cout << “执行独立测试用例Test1” << std::endl;
EXPECT_TRUE(1 == 1);
}

TEST(OtherTest, Test3) { // test3
std::cout << “执行独立测试用例Test3” << std::endl;
EXPECT_FALSE(1 == 0);
}

// 主函数
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

上述示例的执行顺序与输出说明:

  1. 程序启动后,首先执行全局环境的SetUp(输出“全局环境SetUp:执行所有测试前的初始化”);

  2. 执行独立测试用例Test1(test1):先执行Test1的最小环境SetUp(若有),再执行测试逻辑,最后执行Test1的最小环境TearDown(若有);

  3. 执行CalculatorFixture测试套件:
    ① 先执行局部环境SetUpTestCase(输出“局部环境SetUpTestCase:CalculatorFixture测试套件执行前初始化”);
    ② 执行test_f 2-1(AddTest):执行最小环境SetUp → 测试逻辑 → 最小环境TearDown;
    ③ 执行test_f 2-2(SubtractTest):执行最小环境SetUp → 测试逻辑 → 最小环境TearDown;
    ④ 执行test_f 2-3(DivideTest):执行最小环境SetUp → 测试逻辑 → 最小环境TearDown;
    ⑤ 执行局部环境TearDownTestCase(输出“局部环境TearDownTestCase:CalculatorFixture测试套件执行后清理”);

  4. 执行独立测试用例Test3(test3):先执行Test3的最小环境SetUp(若有),再执行测试逻辑,最后执行Test3的最小环境TearDown(若有);

  5. 所有测试用例执行完成后,执行全局环境的TearDown(输出“全局环境TearDown:执行所有测试后的清理”)。

通过这种分级管控机制,可精准控制不同范围资源的创建和释放时机,避免资源冗余占用,同时提升测试代码的可维护性。

#include <gtest/gtest.h>

// 待测试的计算器类
class Calculator {
public:
int Add(int a, int b) { return a + b; }
int Subtract(int a, int b) { return a - b; }
int Multiply(int a, int b) { return a * b; }
int Divide(int a, int b) {
if (b == 0) throw std::invalid_argument(“divide by zero”);
return a / b;
}
};

// 定义测试夹具类
class CalculatorFixture : public testing::Test {
protected:
// 共享的计算器对象
Calculator calc;

// 初始化:每个测试用例执行前调用 void SetUp() override { // 可添加额外初始化逻辑,如设置初始状态 } // 清理:每个测试用例执行后调用 void TearDown() override { // 可添加资源清理逻辑 }

};

// 使用TEST_F定义测试用例,共享CalculatorFixture的资源
TEST_F(CalculatorFixture, AddTest) {
EXPECT_EQ(calc.Add(1, 2), 3);
EXPECT_EQ(calc.Add(-1, -2), -3);
}

TEST_F(CalculatorFixture, SubtractTest) {
EXPECT_EQ(calc.Subtract(5, 3), 2);
EXPECT_EQ(calc.Subtract(3, 5), -2);
}

TEST_F(CalculatorFixture, DivideTest) {
EXPECT_EQ(calc.Divide(6, 2), 3);
ASSERT_THROW(calc.Divide(5, 0), std::invalid_argument);
}

5.2 参数化测试

当需要对同一功能使用多组输入数据进行测试时(如测试加法的多个输入对),可使用参数化测试,避免编写重复代码。步骤如下:

  1. 定义参数类型(如输入值和预期输出的结构体)。

  2. 继承testing::TestWithParam<参数类型>类,创建参数化测试夹具。

  3. 使用TEST_P宏定义测试用例(P=Parameterized),通过GetParam()获取当前测试参数。

  4. 使用INSTANTIATE_TEST_SUITE_P宏注册测试套件,指定测试名称和参数列表。

示例:测试加法的多组输入:

#include <gtest/gtest.h>

// 1. 定义参数类型:输入a、输入b、预期结果
struct AddParam {
int a;
int b;
int expected;
};

// 2. 定义参数化测试夹具
class AddParameterizedTest : public testing::TestWithParam {};

// 3. 使用TEST_P定义测试用例
TEST_P(AddParameterizedTest, MultipleAddCases) {
// 获取当前测试参数
AddParam param = GetParam();
// 待测试的加法逻辑
int result = param.a + param.b;
// 断言结果是否符合预期
EXPECT_EQ(result, param.expected);
}

// 4. 注册测试套件,指定参数列表
INSTANTIATE_TEST_SUITE_P(
AddTestCases, // 测试套件名称(自定义)
AddParameterizedTest, // 参数化测试夹具类名
testing::Values(
AddParam{1, 2, 3}, // 测试用例1:1+2=3
AddParam{-1, -2, -3}, // 测试用例2:-1+(-2)=-3
AddParam{0, 0, 0}, // 测试用例3:0+0=0
AddParam{100, 200, 300} // 测试用例4:100+200=300
)
);

5.3 死亡测试

死亡测试用于验证程序在特定条件下是否会正常退出(如断言失败、调用exit()),gtest通过ASSERT_EXIT、EXPECT_EXIT等宏实现。

示例:测试程序在断言失败时是否退出:

#include <gtest/gtest.h>
#include

// 测试函数:当x<0时触发断言失败
void CheckPositive(int x) {
assert(x > 0); // 断言:x必须为正数
}

TEST(DeathTest, AssertFailure) {
// 断言:调用CheckPositive(-1)时,程序正常退出(退出码非0)
ASSERT_EXIT(
CheckPositive(-1), // 待测试的代码
testing::KilledBySignal(SIGABRT), // 预期:被SIGABRT信号终止(断言失败信号)
“” // 预期的输出信息(为空表示不检查)
);
}

六、gtest测试执行与报告

6.1 测试程序入口

gtest需要在main函数中初始化并运行测试,可直接使用gtest提供的默认main函数(需链接gtest_main.lib),也可自定义main函数:

#include <gtest/gtest.h>

// 自定义main函数(可选)
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv); // 初始化gtest
return RUN_ALL_TESTS(); // 运行所有测试用例
}

6.2 编译与运行

以Linux环境为例,假设有测试文件calc_test.cpp,编译命令如下:

编译测试程序,链接gtest和pthread库(gtest依赖线程库)

g++ calc_test.cpp -o calc_test -lgtest -lpthread

运行测试程序

./calc_test

6.3 测试报告解读

运行测试程序后,gtest会输出详细的测试报告,示例如下:

[==========] Running 5 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 3 tests from AddTestCases/AddParameterizedTest
[ RUN ] AddTestCases/AddParameterizedTest.MultipleAddCases/0
[ OK ] AddTestCases/AddParameterizedTest.MultipleAddCases/0 (0 ms)
[ RUN ] AddTestCases/AddParameterizedTest.MultipleAddCases/1
[ OK ] AddTestCases/AddParameterizedTest.MultipleAddCases/1 (0 ms)
[ RUN ] AddTestCases/AddParameterizedTest.MultipleAddCases/2
[ OK ] AddTestCases/AddParameterizedTest.MultipleAddCases/2 (0 ms)
[----------] 3 tests from AddTestCases/AddParameterizedTest (0 ms total)

[----------] 2 tests from CalculatorFixture
[ RUN ] CalculatorFixture.DivideTest
[ OK ] CalculatorFixture.DivideTest (0 ms)
[ RUN ] CalculatorFixture.SubtractTest
[ OK ] CalculatorFixture.SubtractTest (0 ms)
[----------] 2 tests from CalculatorFixture (0 ms total)

[----------] Global test environment tear-down
[==========] 5 tests passed.
[ PASSED ] 5 tests.

报告关键信息:

  • [==========]:测试开始/结束的分隔线。

  • [ RUN ]:正在执行的测试用例。

  • [ OK ]:测试用例执行成功。

  • [ FAILED ]:测试用例执行失败,会显示失败的断言位置和原因。

  • 最后一行总结:总测试用例数和成功/失败数。

6.4 测试过滤

当测试用例较多时,可通过命令行参数过滤需要执行的测试用例:

只执行测试套件为CalculatorFixture的所有测试用例

./calc_test --gtest_filter=CalculatorFixture.*

只执行测试用例名称包含Add的测试

./calc_test --gtest_filter=Add

排除某个测试用例

./calc_test --gtest_filter=-CalculatorFixture.DivideTest

七、实战案例:测试一个简单的字符串工具类

以下通过实战案例,完整演示gtest的使用流程:测试一个简单的字符串工具类StringUtil,包含字符串拼接、判空、转大写三个功能。

7.1 待测试代码(string_util.h)

#pragma once
#include
#include

class StringUtil {
public:
// 字符串拼接
static std::string Concat(const std::string& a, const std::string& b) {
return a + b;
}

// 判断字符串是否为空(空字符串或全空格) static bool IsEmpty(const std::string& s) { for (char c : s) { if (!isspace(static_cast<unsigned char>(c))) { return false; } } return true; } // 字符串转大写 static std::string ToUpper(const std::string& s) { std::string result; for (char c : s) { result += toupper(static_cast<unsigned char>(c)); } return result; }

};

7.2 测试代码(string_util_test.cpp)

#include <gtest/gtest.h>
#include “string_util.h”

// 测试套件:StringUtil
// 测试用例:ConcatTest(拼接功能测试)
TEST(StringUtil, ConcatTest) {
EXPECT_EQ(StringUtil::Concat(“hello”, “world”), “helloworld”);
EXPECT_EQ(StringUtil::Concat(“”, “test”), “test”);
EXPECT_EQ(StringUtil::Concat(“test”, “”), “test”);
EXPECT_EQ(StringUtil::Concat(“a”, “b”), “ab”);
}

// 测试用例:IsEmptyTest(判空功能测试)
TEST(StringUtil, IsEmptyTest) {
EXPECT_TRUE(StringUtil::IsEmpty(“”)); // 空字符串
EXPECT_TRUE(StringUtil::IsEmpty(" “)); // 全空格
EXPECT_FALSE(StringUtil::IsEmpty(“hello”)); // 非空字符串
EXPECT_FALSE(StringUtil::IsEmpty(” test ")); // 包含非空格字符
}

// 测试用例:ToUpperTest(转大写功能测试)
TEST(StringUtil, ToUpperTest) {
EXPECT_EQ(StringUtil::ToUpper(“hello”), “HELLO”);
EXPECT_EQ(StringUtil::ToUpper(“World”), “WORLD”);
EXPECT_EQ(StringUtil::ToUpper(“123abc”), “123ABC”);
EXPECT_EQ(StringUtil::ToUpper(“”), “”);
EXPECT_EQ(StringUtil::ToUpper(" test "), " TEST ");
}

// 主函数
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

7.3 编译与运行

编译测试程序

g++ string_util_test.cpp -o string_util_test -lgtest -lpthread -std=c++11

运行测试

./string_util_test

7.4 测试结果

[==========] Running 3 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 3 tests from StringUtil
[ RUN ] StringUtil.ConcatTest
[ OK ] StringUtil.ConcatTest (0 ms)
[ RUN ] StringUtil.IsEmptyTest
[ OK ] StringUtil.IsEmptyTest (0 ms)
[ RUN ] StringUtil.ToUpperTest
[ OK ] StringUtil.ToUpperTest (0 ms)
[----------] 3 tests from StringUtil (0 ms total)

[----------] Global test environment tear-down
[==========] 3 tests passed.
[ PASSED ] 3 tests.

所有测试用例执行成功,说明StringUtil类的三个功能符合预期。

八、总结与扩展

本文详细介绍了gtest的安装配置、核心概念、常用断言及进阶功能,并通过实战案例演示了完整的测试流程。gtest作为一款成熟的C++单元测试框架,不仅能满足基础的单元测试需求,其参数化测试、测试夹具等高级功能还能大幅提升测试效率,适配复杂项目的测试场景。

扩展学习:

  • gtest与CI/CD集成:将gtest测试结果输出为XML格式,集成到Jenkins、GitLab CI等持续集成工具。

  • gtest扩展:自定义断言宏、测试监听器,实现个性化的测试需求。

  • gmock:Google的C++模拟框架,与gtest配合使用,用于测试依赖外部接口的代码。

通过熟练掌握gtest,开发者可以构建可靠的测试体系,提前发现代码中的问题,提升软件质量和开发效率。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询