必须先调用 enable_testing(),否则 add_test() 无效;它需在顶层 cmakelists.txt 中早于所有 add_test() 调用,且 ctest 须在构建目录中运行,配合 set_tests_properties() 才能实现标签、超时、环境等可维护特性。

必须先调用 enable_testing(),否则 add_test() 无效
这是最常被忽略的前提。CMake 不默认启用测试支持,add_test() 只有在 enable_testing() 被调用后才真正注册测试条目;否则命令会被静默忽略,ctest 运行时显示 “No tests were found!”。
-
enable_testing()必须出现在顶层CMakeLists.txt中(或至少在包含所有测试定义的add_subdirectory()之前) - 它不接受参数,也不需要放在特定位置(比如不必紧挨着
project()),但必须早于任何add_test() - 多次调用无副作用,但没必要
add_test() 的三种常用写法与适用场景
直接写死命令、包装成可执行目标、或自动发现 Google Test 用例,这三种方式行为和维护成本差异很大。
- 基础形式:
add_test(NAME mytest COMMAND ./test_app --gtest_filter=MySuite.MyCase)—— 适合简单脚本或已构建好的二进制,但路径硬编码易出错 - 推荐形式:
add_test(NAME mytest COMMAND test_app),前提是test_app是通过add_executable(test_app ...)定义的,并且在当前add_test()调用作用域内可见(通常需在同级或上级CMakeLists.txt中定义) - Google Test 自动发现:
gtest_discover_tests(test_app)—— 需要find_package(GTest REQUIRED),且test_app必须链接GTest::gtest_main;它会把每个TEST()或TEST_F()当作独立测试项上报给ctest,但要求 CMake ≥ 3.10
运行 ctest 前必须确保在构建目录中
ctest 不读取源码目录下的 CMakeLists.txt,它只依赖构建目录中由 enable_testing() 生成的 CTestTestfile.cmake 和缓存数据。在源码根目录下直接运行 ctest 会报错或找不到测试。
- 正确做法:先进入构建目录(如
cd build),再执行ctest - 或者显式指定路径:
ctest --test-dir build --output-on-failure - 如果构建目录不是
build,请替换为实际路径;--test-dir参数不可省略,尤其在 CI 脚本中 - 常见错误现象:
Could not find test driver: No such file or directory,基本就是路径错了
set_tests_properties() 是让测试“可维护”的关键
裸奔的 add_test() 只能跑,没法分类、超时控制、环境隔离或跳过。这些都得靠 set_tests_properties() 补齐。
- 按标签过滤:
set_tests_properties(mytest PROPERTIES LABELS "unit;network"),之后可用ctest -L unit只跑单元测试 - 防卡死:
TIMEOUT 30很重要,尤其测试涉及网络或 sleep,避免 CI 流水线挂住 - 预期失败:
WILL_FAIL TRUE用于尚未修复的已知缺陷,失败反而是成功;但注意它不会抑制输出,仍需--output-on-failure查看详情 - 环境变量:
ENVIRONMENT "LD_LIBRARY_PATH=$ORIGIN/../lib"可解决运行时库找不到的问题,比改系统ldconfig更安全
CMakeLists.txt 中的测试逻辑,但忘了重新运行 cmake -S . -B build,旧的 CTestTestfile.cmake 就不会更新,ctest 仍执行老配置。这个细节没有错误提示,只能靠经验排查。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











