ctest是cmake自带的测试子系统,只需在顶层cmakelists.txt中调用enable_testing()和add_test()即可启用;add_test()的command必须用$确保路径正确,测试需设working_directory并处理rpath依赖。

CTest 不是“集成到 CMake”,它就是 CMake 自带的测试子系统——只要调用 enable_testing() 和 add_test(),就完成了最核心的集成。 不需要额外安装、不依赖外部包管理器,也不用写 shell 脚本胶水层。难点不在“怎么连”,而在“怎么组织才不重复、不漏测、不卡 CI”。
enable_testing() 必须在顶层 CMakeLists.txt 中调用
很多人把 enable_testing() 放在 tests/CMakeLists.txt 里,结果 ctest 运行时提示 “No tests were found”。这是因为 CTest 只扫描构建树根目录下的 CTestTestfile.cmake 文件,而该文件由顶层 enable_testing() 生成。子目录里的调用无效。
- 只在项目根
CMakeLists.txt的project()之后、任何add_subdirectory(tests)之前调用一次enable_testing() - 推荐配合缓存变量控制:
option(BUILD_TESTING "Build the testing tree." ON),再用if(BUILD_TESTING)包裹整个测试逻辑,避免用户禁用时仍尝试链接测试依赖 - 如果用了
include(CTest),反而可能干扰默认行为——现代 CMake(≥3.10)不需要显式 include
add_test() 的 COMMAND 参数必须指向可执行目标或完整路径
add_test() 不会自动编译、不解析依赖、不补路径。它只负责把一条命令注册进 CTest。常见错误是直接写 COMMAND TestMathFunctions add,但没确保 TestMathFunctions 已构建且在 PATH 中。
CMake 4.3.2 Windows x86_64 历史版本安装包,适合旧项目兼容、构建环境回退、CMakeLists.txt 迁移验证、Visual Studio/Ninja/Makefile 生成器测试和 C/C++ 项目维护。
- 正确做法:用生成器表达式
$<testmathfunctions></testmathfunctions>,它会在构建时自动展开为绝对路径,比如/path/to/build/tests/TestMathFunctions - 带参数时写全:
add_test(NAME sqrt COMMAND $<testmathfunctions> sqrt)</testmathfunctions>,别省略sqrt - 不要用
COMMAND sh -c "..."包一层——除非真需要 shell 特性(如管道、条件判断),否则增加启动开销且跨平台脆弱 - 若测试程序需读取数据文件,务必设
WORKING_DIRECTORY,否则相对路径会从构建目录开始算,不是源码目录
批量运行靠 ctest 命令行选项,不是靠 CMakeLists 写一堆 add_test
有人为每个测试用例手写 20 条 add_test(),结果维护爆炸。其实 CTest 天然支持批量发现和筛选,关键在测试命名与分组设计。
- 用
-R按正则匹配名称:ctest -R "^math_.*"运行所有以math_开头的测试 - 用
--label-regex按标签过滤(需提前设属性):set_property(TEST mytest PROPERTY LABELS "unit;math"),再运行ctest -L unit - 并行跑满 CPU:
ctest -j$(nproc)(Linux/macOS)或ctest -j%NUMBER_OF_PROCESSORS%(Windows) - 失败时才输出详情:
ctest --output-on-failure,比-V更适合 CI 日志排查
最容易被忽略的是测试可执行文件的依赖链:如果你的 TestMathFunctions 链接了 MathFunctions 动态库,但没把该库的安装路径加进 RPATH 或 LD_LIBRARY_PATH,ctest 就会报 error while loading shared libraries —— 它在构建目录里运行,不是在 install 目录。解决方法是 set_target_properties(TestMathFunctions PROPERTIES INSTALL_RPATH "$ORIGIN/../lib") 或直接静态链接测试目标。










