我们在开发中常会遇到这样的情况:一个函数写完了,运行程序看起来没问题,就算“搞定”了。
但是…
如果你给它传入一个非法参数?别人修改了它的依赖逻辑?
如果你不管它们,那么这些被遗忘在角落“潜在问题”以后可能就会出 bug。
于是,单元测试就成为写稳健代码的利器。
但是,许多开发者因时间压力或认为集成测试足够而抗拒单元测试。
因此,本文想做的,就是用一个小例子告诉你:
原来写单元测试并不难,哪怕你从没接触过
GTest
,跟着做一遍你就知道它的价值。
GTest简介
Google Test (GTest) 是 Google 出品的 C++ 单元测试框架,具备以下特点:
- 易用的断言机制:比如
EXPECT_EQ
,ASSERT_TRUE
- 自动发现测试用例和报告结果
- 支持测试夹具、参数化测试等高级功能
- 与生产代码分离,编译独立
它是目前 C++ 社区最主流的单元测试框架之一。
单元测试示例
接下来,我们从零开始构建一个简单的单元测试示例。(代码不用复制,文末有工程链接)
项目结构
project/
├── build
├── CMakeLists.txt
├── include
│ └── my_math.h
├── src
│ ├── CMakeLists.txt
│ └── my_math.cc
├── third_party
│ └── googletest
└── unit_test
├── CMakeLists.txt
└── my_math_test.cc
为了更加直观的表现对GTest的使用,这里手动下载GTest源码,然后将解压出来的googletest拷贝到third_party中使用。
也可以使用FetchContent等方式,有兴趣的可以深入研究下。
核心代码
include/my_math.h
#pragma once
int Add(int a, int b);
src/my_math.cc
#include "my_math.h"
int Add(int a, int b) {
return a + b;
}
测试代码
unit_test/my_math_test.cc
#include <gtest/gtest.h>
#include "my_math.h"
TEST(MyMathTest, AddWorks) {
// 判断计算结果是否等于5
EXPECT_EQ(Add(2, 3), 5);
// 判断计算结果是否等于0
EXPECT_EQ(Add(-1, 1), 0);
}
CMake配置详解
顶层CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(unit_test_demo)
set(CMAKE_CXX_STANDARD 17)
# 设置GTest版本
set(GOOGLETEST_VERSION "1.17.0" CACHE STRING "GTest version")
# 添加源码
add_subdirectory(src)
# 添加测试
enable_testing()
# 添加GTest源码
add_subdirectory(third_party/googletest)
# 添加测试代码
add_subdirectory(unit_test)
src/CMakeLists.txt
# 将my_math.cc编译为静态库,待测
add_library(my_math my_math.cc)
target_include_directories(my_math PUBLIC ${PROJECT_SOURCE_DIR}/include)
unit_test/CMakeLists.txt
# 创建测试可执行文件
add_executable(math_test my_math_test.cc)
# 链接gtest_main和待测试的my_math库
target_link_libraries(math_test
gtest_main
my_math
)
# 加载 GTest 模块并注册测试
include(GoogleTest)
gtest_discover_tests(math_test)
构建与执行测试
构建项目
cd project
mkdir build && cd build
cmake .. # 生成构建系统
make # 编译项目及测试
运行测试
直接运行测试程序
unit_test/math_test
示例输出:
也可以直接执行
ctest
命令
以上就是搭建一个简单单元测试环境的过程。
后面我们可以在这个基础上增添功能,进行更加复杂的测试,比如代码覆盖率、Mock等。
结语
写单元测试,不是为了形式主义,不是为了指标,而是为了:
- 把 bug 扼杀在最早期,而不是等上线再翻车
- 给自己重构的勇气
- 给团队传递信任和文档
- 满足 ASPICE 等流程认证要求
希望本文能成为你 GTest 入门的起点~
代码仓库: https://github.com/LeafTime/GTest
本文首发于微信公众号《Linux在秋名山》,欢迎大家关注~