You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Google Test保留静态局部变量值,解决CMake make test重置问题

问题根因

你遇到的现象本质是CMake配套的CTest工具的默认行为导致的:

如果你使用了gtest_discover_tests命令注册GTest测试用例,CMake会在构建/测试阶段自动扫描二进制内的所有TEST/TEST_F定义,把每一个GTest用例都注册为独立的CTest测试项。执行make test时,CTest会为每一个测试项单独启动测试二进制进程,通过--gtest_filter参数指定只运行当前用例,因此函数内的静态局部变量每次都会被初始化,才会出现和直接运行整个二进制结果不一致的问题。

解决方案

方案1:调整CMake测试注册逻辑,不拆分单个测试用例(最贴合你需求)

放弃自动拆分GTest用例的逻辑,直接把整个测试二进制作为单个CTest测试项,运行时只会启动一次进程,所有测试用例按GTest默认顺序在同一个进程内执行:

  1. 删除你CMakeLists.txt中原有的gtest_discover_tests(你的测试目标名)行
  2. 改用add_test直接注册整个测试二进制:
add_test(
  NAME 你的测试项名称(比如MyModuleUnitTests)
  COMMAND 你的测试目标名
)

这个方案的优点是不需要修改业务代码和测试代码,完全符合你要的「所有测试在同一个实例按顺序运行」的要求,缺点是CTest只会显示整个测试包的最终结果,不会单独统计每个GTest用例的运行状态,你需要看测试输出才能知道具体哪个用例失败。


方案2:保留拆分测试用例的能力,修改业务代码添加测试专用重置接口(单元测试最佳实践)

单元测试的设计原则是每个用例完全独立,不依赖其他用例的运行状态和执行顺序,因此更推荐你修改少量业务代码适配测试场景,不需要修改CMake配置:

  1. 把原函数内的静态局部变量last_buffer_idx移到文件作用域(仍用static修饰,不对外暴露,不影响原有作用域规则)
  2. 新增单元测试专用的状态重置接口,仅在单元测试编译时生效:
// 原函数所在的.c文件
static uint32_t last_buffer_idx = 0u;

#ifdef UNIT_TEST
// 仅单元测试编译时导出该接口
void test_reset_myfunction_state(void) {
  last_buffer_idx = 0u;
}
#endif

process_result_t myFunction(void) {
  // 原有逻辑,直接使用文件作用域的last_buffer_idx即可,不需要修改原有代码逻辑
  ...
}
  1. 在你的GTest测试用例的SetUp方法中,每个用例运行前调用test_reset_myfunction_state()重置状态,保证每个用例的初始状态一致。
    这个方案的优点是完全符合单元测试规范,不管CTest怎么运行测试都不会出现状态不一致的问题,同时保留了CTest拆分单个用例统计结果的能力。

方案3:开启gtest_discover_tests的批量运行模式(需要CMake 3.18+)

如果你既要保留CTest拆分每个用例统计结果的能力,又要让所有用例在同一个进程中运行,可以给gtest_discover_tests添加DISCOVERY_MODE PRE_TEST和XML_OUTPUT_DIR参数:

gtest_discover_tests(你的测试目标名
  DISCOVERY_MODE PRE_TEST
  XML_OUTPUT_DIR ${CMAKE_BINARY_DIR}/test-reports
)

这个模式下CTest会一次性启动测试二进制运行所有用例,生成XML测试报告后再解析每个用例的结果分别展示,不会重复启动进程,也能保留单个用例的统计能力。

内容的提问来源于stack exchange,提问作者Walkingbeard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 11:15:03