C++中doctest独立测试主函数无法识别生产代码内测试的问题
解决方案
核心思路
doctest默认会在非测试编译环境下禁用测试代码,所以需要通过预定义宏+CMake配置,让生产代码中的测试仅在编译测试二进制时被激活,同时将生产代码逻辑与测试代码合并到同一测试可执行文件中,且不影响原生产main函数。
1. 生产代码中包裹测试逻辑
在src目录的源文件中,用#ifdef DOCTEST_INCLUDE_TESTS包裹测试代码,确保只有编译测试时才会包含这部分代码,生产编译时自动排除:
// src/foo.cpp // 生产逻辑代码 int add(int a, int b) { return a + b; } // 仅在测试编译时生效的测试代码 #ifdef DOCTEST_INCLUDE_TESTS #include <doctest/doctest.h> TEST_CASE("add函数功能验证") { CHECK(add(1, 2) == 3); CHECK(add(-1, 1) == 0); } #endif
注意:不要在头文件中写测试代码,避免因头文件被多次包含导致测试用例重复定义。
2. 调整CMake配置
通过CMake区分生产编译和测试编译的宏定义,同时将生产代码逻辑链接到测试可执行文件中:
推荐方案:将生产代码封装为库
# 1. 编译生产代码为静态库(分离逻辑与入口) add_library(my_project_lib STATIC src/foo.cpp src/bar.cpp ) # 2. 生产可执行文件(保留原main函数) add_executable(my_project src/main.cpp) target_link_libraries(my_project PRIVATE my_project_lib) # 3. 测试可执行文件 add_executable(my_project_test test/test_main.cpp test/complex_test.cpp # 独立复杂测试文件 ) # 编译测试时定义宏,激活生产代码中的测试 target_compile_definitions(my_project_test PRIVATE DOCTEST_INCLUDE_TESTS) # 链接生产库,将生产代码中的测试逻辑引入测试二进制 target_link_libraries(my_project_test PRIVATE my_project_lib) # 指定doctest头文件路径(根据实际路径调整) target_include_directories(my_project_test PRIVATE ${CMAKE_SOURCE_DIR}/third_party/doctest)
备选方案:直接复用生产源文件(不封装库)
如果不想封装库,可将生产源文件(除main.cpp外)直接加入测试可执行的编译列表:
# 生产可执行文件 add_executable(my_project src/main.cpp src/foo.cpp src/bar.cpp ) # 测试可执行文件(不包含src/main.cpp,避免多main冲突) add_executable(my_project_test test/test_main.cpp test/complex_test.cpp src/foo.cpp src/bar.cpp ) target_compile_definitions(my_project_test PRIVATE DOCTEST_INCLUDE_TESTS) target_include_directories(my_project_test PRIVATE ${CMAKE_SOURCE_DIR}/third_party/doctest)
3. 保持测试main.cpp的正确写法
test目录下的test_main.cpp仅需保留doctest的main实现,无需额外逻辑:
// test/test_main.cpp #define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN #include <doctest/doctest.h>
验证效果
- 编译生产版本:无
DOCTEST_INCLUDE_TESTS宏,生产代码中的测试被预编译排除,原main函数正常运行,生产二进制无测试冗余。 - 编译测试版本:激活宏后,生产代码中的测试与test目录的测试被统一收集,运行测试二进制即可执行所有用例。
内容的提问来源于stack exchange,提问作者Vinícius Ferrão
相关产品推荐
相关产品推荐

