news 2026/4/3 4:47:46

C++ TDD 入门:从搭建 GTest 框架到第一个示例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++ TDD 入门:从搭建 GTest 框架到第一个示例

C++ TDD 入门:从搭建 GTest 框架到第一个示例

你想要入门 C++ 语言的 TDD 实践,核心是先搭建测试框架环境,再遵循「红-绿-重构」的循环落地最小功能单元。下面我会以Google Test(GTest,C++ 最主流的 TDD 测试框架)为例,提供从「环境搭建→第一个 TDD 示例→完整循环落地」的分步指南,适配 Linux(CentOS/Ubuntu)环境,新手也能快速上手。


一、前置准备

  1. 环境:Linux 系统(CentOS 8/9 或 Ubuntu 18.04+),已安装g++(C++ 编译器)、cmake(构建工具)、git(拉取 GTest 源码)。

  2. 验证编译器是否安装:

    g++ --version cmake --version
  3. 若未安装,执行以下命令补装:

    # CentOS/RHEL dnf install -y gcc gcc-c++ cmake git # Ubuntu/Debian apt update && apt install -y g++ cmake git

二、步骤1:搭建 Google Test(GTest)环境

GTest 是 C++ 最成熟、最常用的单元测试框架,支持 TDD 所需的自动化测试、断言判断、测试用例隔离等核心功能,我们采用「源码编译安装」(确保版本最新,适配性更好)。

1.1 拉取 GTest 源码

# 创建工作目录,后续所有操作均在该目录下进行 mkdir -p ~/cpp_tdd_demo && cd ~/cpp_tdd_demo # 拉取 GTest 源码(官方镜像,稳定版) git clone https://github.com/google/googletest.git

1.2 编译并安装 GTest

GTest 采用 CMake 构建,执行以下命令编译安装(安装到系统全局,后续所有项目均可直接引用):

# 进入 googletest 目录,创建构建目录 cd googletest && mkdir build && cd build # 生成 Makefile(指定安装路径为 /usr/local,系统全局可访问) cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local # 编译(-j 后接CPU核心数,加快编译速度,如 -j4) make -j4 # 安装到系统(root 权限,需输入密码) sudo make install

1.3 验证 GTest 安装是否成功

安装完成后,系统会在/usr/local/include/生成gtest/头文件目录,在/usr/local/lib64/(CentOS)或/usr/local/lib/(Ubuntu)生成库文件,验证命令:

# 查看头文件是否存在 ls /usr/local/include/gtest # 查看库文件是否存在 ls /usr/local/lib64 | grep gtest # CentOS # ls /usr/local/lib | grep gtest # Ubuntu

若能看到gtest.h头文件和libgtest.alibgtest_main.a库文件,说明安装成功。


三、步骤2:C++ TDD 入门示例(实现一个简单的加法函数)

我们以「实现一个整数加法函数int Add(int a, int b)」为例,完整遵循 TDD 「红-绿-重构」循环,这是最适合新手的入门案例。

项目结构说明

先创建清晰的项目结构(TDD 项目需分离「测试代码」和「业务代码」,便于维护):

# 回到 cpp_tdd_demo 目录,创建项目结构 cd ~/cpp_tdd_demo mkdir -p add_demo/{src,test} cd add_demo
  • src/:存放业务代码(.h 头文件、.cpp 实现文件);

  • test/:存放 GTest 测试用例代码;

  • 后续会在add_demo/下创建CMakeLists.txt,用于构建整个项目。


循环1:红(Red)- 编写失败的测试用例

核心:先写测试用例,明确功能预期,此时无业务代码,测试必然失败

2.1 编写测试用例代码

进入test/目录,创建测试文件test_add.cpp

vim test/test_add.cpp

粘贴以下代码(GTest 测试用例的标准写法):

// 引入 GTest 核心头文件 #include <gtest/gtest.h> // 引入业务代码头文件(此时还未创建,先声明函数,保证编译不报错) // 后续会创建 src/add.h,这里先提前声明 int Add(int a, int b); // 定义测试套件(Test Suite):命名为 AddFunctionTest,对应要测试的模块 TEST(AddFunctionTest, NormalInputTest) { // 断言(Assert):判断 Add(1, 2) 的返回值是否等于 3 // EXPECT_EQ:预期相等,若不相等则测试失败(不会终止整个测试进程) // GTest 还有 ASSERT_EQ(断言失败则终止当前测试用例),新手优先用 EXPECT_* EXPECT_EQ(Add(1, 2), 3); EXPECT_EQ(Add(0, 0), 0); EXPECT_EQ(Add(-1, 1), 0); EXPECT_EQ(Add(100, 200), 300); } // 测试套件的第二个测试用例:测试边界值(TDD 要求覆盖边界条件) TEST(AddFunctionTest, BoundaryInputTest) { EXPECT_EQ(Add(INT_MAX, 0), INT_MAX); // 最大整数 + 0 EXPECT_EQ(Add(INT_MIN, 0), INT_MIN); // 最小整数 + 0 } // GTest 主函数:用于运行所有测试用例(可直接复用,无需修改) // 也可以不写该主函数,编译时链接 libgtest_main.a 即可 int main(int argc, char **argv) { // 初始化 GTest testing::InitGoogleTest(&argc, argv); // 运行所有测试用例 return RUN_ALL_TESTS(); }

保存退出(Esc:wq)。

2.2 编写 CMake 构建文件

回到add_demo/目录,创建CMakeLists.txt,用于构建测试项目:

vim CMakeLists.txt

粘贴以下内容:

# 要求 CMake 最低版本 cmake_minimum_required(VERSION 3.10) # 项目名称:cpp_tdd_add_demo project(cpp_tdd_add_demo) # 设置 C++ 标准(C++11 及以上均可) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 包含头文件目录(src/ 目录,后续存放业务头文件) include_directories(${PROJECT_SOURCE_DIR}/src) # 查找 GTest 库(系统全局安装,可直接找到) find_package(GTest REQUIRED) include_directories(${GTEST_INCLUDE_DIRS}) # 构建测试可执行文件:test_add(对应 test/test_add.cpp) add_executable(test_add test/test_add.cpp) # 链接 GTest 库和 pthread 库(GTest 依赖线程库) target_link_libraries(test_add ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread)

保存退出。

2.3 编译并运行测试(预期失败)

执行以下命令构建并运行测试,验证「红阶段」:

# 创建构建目录 mkdir build && cd build # 生成 Makefile cmake .. # 编译 make -j4

此时编译会报错(提示undefined reference to Add(int, int)),因为我们只声明了Add函数,没有实现业务代码,这是「红阶段」的正常现象(测试用例无法运行,更无法通过)。


循环2:绿(Green)- 编写最简化业务代码让测试通过

核心:仅编写刚好能让测试用例通过的业务代码,不做多余设计

2.4 编写业务代码头文件

进入src/目录,创建add.h头文件:

vim src/add.h

粘贴以下内容(声明加法函数):

#ifndef ADD_H // 防止头文件重复包含(C++ 工程规范) #define ADD_H #include <climits> // 引入 INT_MAX/INT_MIN 定义 // 加法函数声明 int Add(int a, int b); #endif // ADD_H

2.5 编写业务代码实现文件

src/目录下创建add.cpp,实现Add函数:

vim src/add.cpp

粘贴以下最简化实现代码(仅满足测试用例要求,不考虑优化):

// 引入头文件 #include "add.h" // 加法函数实现:最简化逻辑,直接返回 a + b int Add(int a, int b) { return a + b; }

2.6 更新 CMakeLists.txt(包含业务代码)

修改add_demo/CMakeLists.txt,将src/add.cpp加入编译:

vim ../CMakeLists.txt # 若在 build 目录下,需回到上一级

找到add_executable(test_add test/test_add.cpp),修改为:

# 包含业务代码 add.cpp,一起编译 add_executable(test_add test/test_add.cpp src/add.cpp)

2.7 重新编译并运行测试(预期成功)

# 若在 build 目录下,直接执行 make -j4 # 运行测试可执行文件 ./test_add

此时会输出 GTest 测试结果,若看到[ PASSED ] 2 tests.,说明测试用例全部通过,「绿阶段」完成!典型成功输出:

[==========] Running 2 tests from 1 test suite. [----------] Global test environment set-up. [----------] 2 tests from AddFunctionTest [ RUN ] AddFunctionTest.NormalInputTest [ OK ] AddFunctionTest.NormalInputTest (0 ms) [ RUN ] AddFunctionTest.BoundaryInputTest [ OK ] AddFunctionTest.BoundaryInputTest (0 ms) [----------] 2 tests from AddFunctionTest (0 ms total) [==========] 2 tests passed.

循环3:重构(Refactor)- 优化代码且保持测试通过

核心:修改代码结构,不改变功能,测试用例始终保持通过

当前的Add函数逻辑简单,可优化的点不多,我们以「增加异常处理(避免整数溢出)+ 规范代码注释 + 优化代码可读性」为例进行重构。

2.8 重构业务代码(add.cpp)

修改src/add.cpp,增加整数溢出判断,优化代码:

#include "add.h" #include <stdexcept> // 引入异常处理头文件 /** * @brief 整数加法函数,支持正常整数相加,避免溢出 * @param a 第一个整数 * @param b 第二个整数 * @return 两数之和 * @throw std::overflow_error 若相加结果溢出则抛出异常 */ int Add(int a, int b) { // 重构:增加整数溢出判断(避免 undefined behavior) // 情况1:正数 + 正数 溢出 if (a > 0 && b > 0 && a > INT_MAX - b) { throw std::overflow_error("Positive integer overflow"); } // 情况2:负数 + 负数 溢出 if (a < 0 && b < 0 && a < INT_MIN - b) { throw std::overflow_error("Negative integer overflow"); } // 原有功能逻辑不变,保证测试用例通过 return a + b; }

2.9 重构测试用例(补充异常测试)

修改test/test_add.cpp,增加溢出异常的测试用例(TDD 重构阶段可补充完善测试用例,覆盖新的场景):

// 新增测试用例:测试溢出异常 TEST(AddFunctionTest, OverflowTest) { // EXPECT_THROW:预期函数抛出指定类型的异常,否则测试失败 EXPECT_THROW(Add(INT_MAX, 1), std::overflow_error); EXPECT_THROW(Add(INT_MIN, -1), std::overflow_error); }

2.10 重新编译并运行测试(确保重构后测试通过)

# 编译(build 目录下) make -j4 # 运行测试 ./test_add

此时应看到[ PASSED ] 3 tests.,说明重构后的代码功能正常,且新增了异常处理,代码质量更高,「重构阶段」完成。


四、TDD 核心补充(C++ 专属)

1. GTest 常用断言(新手必备)

TDD 中核心是通过断言判断功能是否符合预期,GTest 提供了两类断言,优先使用EXPECT_*

断言类型功能示例
EXPECT_EQ(a, b)预期 a == b(相等)EXPECT_EQ(Add(1,2),3)
EXPECT_NE(a, b)预期 a != b(不相等)EXPECT_NE(Add(1,2),4)
EXPECT_GT(a, b)预期 a > b(大于)EXPECT_GT(Add(2,3),4)
EXPECT_LT(a, b)预期 a < b(小于)EXPECT_LT(Add(1,2),4)
EXPECT_THROW(func, ex)预期 func 抛出 ex 异常EXPECT_THROW(Add(INT_MAX,1), std::overflow_error)

2. C++ TDD 项目的最佳实践

  1. 分离业务代码与测试代码:始终保持src/(业务)和test/(测试)目录分离,避免测试代码污染业务代码;

  2. 测试用例独立无依赖:每个测试用例不依赖其他用例的执行结果,不依赖外部环境(如文件、数据库),可通过「模拟对象(Mock)」隔离外部依赖(GTest 可结合 GMock 实现);

  3. 小步迭代:每次只实现一个最小功能单元(如先实现正常输入的加法,再实现边界值,最后实现异常处理);

  4. 重构优先保证测试通过:重构过程中可多次执行./test_add,确保所有测试用例始终通过,避免引入新 Bug;

  5. 自动化构建:结合 CI/CD 工具(如 Jenkins),每次提交代码自动编译并运行测试用例,实现持续验证。

3. 常见误区

  1. 先写业务代码再补测试:违背 TDD 「测试先行」原则,失去 TDD 驱动设计的意义;

  2. 测试用例覆盖不全:只测试正常场景,忽略边界值、异常场景,导致代码鲁棒性不足;

  3. 重构阶段修改功能:重构只优化代码结构,不改变功能,若需新增功能,应重新进入「红-绿-重构」循环。


五、总结

  1. 环境搭建核心:编译安装 GTest 并配置 CMake,实现测试代码与业务代码的编译链接;

  2. TDD 核心循环:红(编写失败测试用例)→ 绿(编写最简业务代码让测试通过)→ 重构(优化代码且保持测试通过),无限重复直至功能完成;

  3. C++ 专属要点:使用 GTest 断言判断结果,分离业务/测试目录,重构时增加异常处理等工程化优化;

  4. 入门关键:从简单功能(如加法、减法)入手,熟悉 GTest 用法和 TDD 循环,再逐步推进到复杂功能。

这个示例完成后,你可以尝试扩展功能(如实现减法、乘法函数),按照相同的 TDD 循环落地,逐步掌握 C++ TDD 的核心思维。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/28 0:46:06

2026 年热门 AI 写论文工具全攻略(含详细使用步骤)

以下是当前学术圈口碑 TOP 的6 款 AI 写论文工具&#xff0c;覆盖从选题、开题到降重、答辩的论文全流程&#xff0c;剔除冗余工具&#xff0c;每款均附分步骤实操指南场景适配技巧&#xff0c;重点突出中文论文适配性&#xff0c;新手也能快速上手&#xff0c;效率翻倍。一、全…

作者头像 李华
网站建设 2026/2/28 11:35:05

2026年低代码革命:软件测试从业者的十大生存法则

引言&#xff1a;测试角色的范式转移 当Gartner预测2026年70%的新应用将依赖低代码开发时&#xff0c;传统测试流程的根基已被动摇。AI驱动的自然语言转代码技术使基础开发效率跃升60%&#xff0c;但随之而来的是测试场景复杂化、缺陷隐蔽性增强等挑战。本文从测试工程师视角&…

作者头像 李华
网站建设 2026/4/1 15:06:18

不踩雷!AI论文平台 千笔写作工具 VS 学术猹,继续教育专属利器

随着人工智能技术的迅猛迭代与普及&#xff0c;AI辅助写作工具已逐步渗透到高校学术写作场景中&#xff0c;成为专科生、本科生、研究生完成毕业论文不可或缺的辅助手段。越来越多面临毕业论文压力的学生&#xff0c;开始依赖各类AI工具简化写作流程、提升创作效率。但与此同时…

作者头像 李华
网站建设 2026/3/29 5:29:28

PHP开源进销存系统源码,提供强大的多仓库/多仓位管理功能

温馨提示&#xff1a;文末有资源获取方式在数字化浪潮席卷各行各业的今天&#xff0c;一套能精准管控企业物流、资金流与信息流的进销存系统&#xff0c;已成为中小企业降本增效、实现信息化转型的刚需。今天&#xff0c;我们隆重推出一款功能空前强大的ERP进销存管理系统源码&…

作者头像 李华
网站建设 2026/3/28 19:53:50

手把手教你本地部署deepseek大模型

自从DeepSeek R1出来以后&#xff0c;基本上给替代了。经过对比&#xff0c;DeepSeek是能够满足日常使用的&#xff0c;并且还说免费&#xff0c;你说香不香 可能是全球爆火&#xff0c;用的人太多了&#xff0c;并且也经常被攻击&#xff0c;所以DeepSeek经常出现用不了的情况…

作者头像 李华
网站建设 2026/3/11 22:00:35

作为开发,该如何给产品提有效建议

——一套真正不翻车的方法论 写代码多年后我才意识到&#xff1a; 开发给产品提意见&#xff0c;拼的不是“对不对”&#xff0c;而是“值不值得、能不能、现在该不该”。 很多开发都有类似经历&#xff1a; 明明觉得设计不合理 明明知道有更优方案 但一开口就变成了「你这个…

作者头像 李华