如何让CMake/CTest单次运行全部Google Test用例,避免重复初始化?
解决CTest逐个执行Google Test二进制文件的耗时问题
你的问题根源在于gtest_discover_tests默认会让CTest为每个测试用例单独启动一次测试二进制,通过--gtest_filter指定单个测试,导致重复执行2秒的初始化流程。以下是几种可行的解决方法:
方法1:直接注册整个测试二进制(最简便)
放弃使用gtest_discover_tests,改用add_test直接注册整个测试目标,这样CTest只会启动一次二进制文件,一次性执行所有测试:
# 假设你的测试二进制名为MyTests add_executable(MyTests test_main.cpp [其他测试源文件]) target_link_libraries(MyTests GTest::gtest GTest::gtest_main) # 注册整个测试,替代gtest_discover_tests add_test(NAME AllMyTests COMMAND MyTests)
优点:彻底解决重复初始化问题,测试耗时回到预期的10分钟左右,配置简单。
缺点:CTest的测试报告中只会显示一个名为AllMyTests的条目,无法单独查看或运行单个测试用例。如果需要单独运行某个测试,可以手动指定过滤器:
ctest -R "AllMyTests" --test-command "MyTests --gtest_filter=TargetTestName"
方法2:使用CMake 3.20+的批量发现模式
如果需要保留单个测试用例的可追踪性,同时避免重复初始化,可以利用CMake 3.20引入的TEST_DISCOVERY_MODE属性,设置为BATCH模式:
add_executable(MyTests test_main.cpp [其他测试源文件]) target_link_libraries(MyTests GTest::gtest GTest::gtest_main) # 启用批量测试发现模式 set_tests_properties(MyTests PROPERTIES TEST_DISCOVERY_MODE BATCH) gtest_discover_tests(MyTests)
这种模式下,gtest_discover_tests会生成一个批量执行的测试命令,一次性运行所有发现的测试用例,只初始化一次,同时CTest仍能显示每个测试用例的单独结果。
方法3:手动构造测试过滤器(兼容旧版CMake)
如果你的CMake版本低于3.20,可以通过手动解析测试用例列表,构造包含所有测试的过滤器,再注册整体测试:
add_executable(MyTests test_main.cpp [其他测试源文件]) target_link_libraries(MyTests GTest::gtest GTest::gtest_main) # 运行测试二进制获取所有测试用例列表 execute_process( COMMAND MyTests --gtest_list_tests OUTPUT_VARIABLE GTEST_TESTS_OUTPUT WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE GTEST_LIST_RESULT ) if(NOT GTEST_LIST_RESULT EQUAL 0) message(FATAL_ERROR "Failed to list Google Test cases for MyTests") endif() # 解析输出,构造gtest_filter字符串 string(REGEX REPLACE "^#.*$" "" GTEST_TESTS_OUTPUT "${GTEST_TESTS_OUTPUT}") string(REGEX REPLACE "\n([a-zA-Z0-9_]+)\." "\n\\1:" GTEST_TESTS_OUTPUT "${GTEST_TESTS_OUTPUT}") string(REGEX REPLACE "\n[ ]+([a-zA-Z0-9_]+)" ":\\1" GTEST_TESTS_OUTPUT "${GTEST_TESTS_OUTPUT}") string(REGEX REPLACE "\n" ";" GTEST_FILTER_LIST "${GTEST_TESTS_OUTPUT}") list(JOIN GTEST_FILTER_LIST "," GTEST_FILTER) # 注册整体测试 add_test(NAME AllMyTests COMMAND MyTests --gtest_filter=${GTEST_FILTER})
注意:这种方法需要在CMake配置阶段运行测试二进制,因此测试代码必须在配置前编译完成(可以用add_custom_command先编译测试),否则会失败。
内容的提问来源于stack exchange,提问作者user5706966
相关产品推荐
相关产品推荐

