要在CMake下注册测试,我们需要
enable_testing()
或
include(CTest)
然后针对每个单一测试(名称fooTest
,可执行文件foo
)
add_executable(foo <foo_sources>)
add_test(fooTest foo)
然后可以使用命令ctest
运行测试。
此外,我们可以使用命令make check
运行测试,只要我们添加一次
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND})
并且对于每个测试,我们通过关键字EXCLUDE_FROM_ALL
和命令add_dependencies
扩展上述内容:
add_executable(foo EXCLUDE_FROM_ALL <foo_sources>)
add_test(fooTest foo)
add_dependencies(check foo)
理想情况下,这会使make check
成为ctest
的别名。至少有两个原因并非如此:
(1)make check
存在缺陷,因为它没有将选项传递给ctest
[2]。特别是,ctest -j4
将并行运行4个测试,而make -j4 check
将在目标check
上的一个线程中工作,其他三个线程将保持空闲状态。
(2)ctest
有缺陷[3,4],因为所有测试都是在all
目标下构建的,即与主应用程序一起构建。在某些情况下,这可能是期望的行为,但在其他情况下,应该可以推迟构建,直到要运行测试。
这是否正确总结了当前的事态?
有没有办法(吃蛋糕并拥有它)?
[1] https://cmake.org/Wiki/CMakeEmulateMakeCheck [2] http://comments.gmane.org/gmane.comp.programming.tools.cmake.user/47300 [3] CMake & CTest : make test doesn't build tests [4] http://public.kitware.com/Bug/view.php?id=8774
答案 0 :(得分:3)
首先,我要注意ctest
和make test
只是简单的命令行工具,用于简单的测试任务。如果您需要一个用于严格测试的工具,请使用CDash,Buildbot,Jenkins或其他任何工具。
关于CTest的缺陷:有意识的是,对CTest的调用不构建测试。在几种情况下这是一个坏主意:
Autotools以您想要的方式做到了,人们已经习惯了。但为什么它应该是一个单位呢?为什么不用两个命令?混合两项任务的好处是什么,使有特殊需要的项目更加困难?
我得出结论,创建一个目标build-tests
或类似的目标,并遵循CMake开发人员的决定来解耦构建测试和执行测试。然后我可以决定是否需要并行构建,如何处理编译失败(例如,将-k
传递给make)等等。
唯一的缺点是,此目标仅存在于顶级目录中,不能在子目录中使用
要获得CMake内置的这样一个目标,这将是一个很好的功能请求。 Ranting on SO并不好。
答案 1 :(得分:1)
CTest根本没有缺陷,但你使用CMake和CTest的方式似乎有缺陷&#34;。命令行界面(CLI)工具ctest
的调用通常与CMake构建目标的调用无关(目标test
除外)。
在我看来,CMake Wiki中描述的自定义check
目标解决方案应该不,因为它会更改CMake的默认行为,并且不可配置。
相反,应使用以下使用内置选项BUILD_TESTING
的方法:
include(CTest)
if(BUILD_TESTING)
find_package(GTest MODULE REQUIRED)
add_executable(example_test example_test.cpp)
target_link_libraries(
example_test
PRIVATE
GTest::GTest
GTest::Main
)
add_test(NAME example_test COMMAND example_test)
endif()
include(CTest)
在option BUILD_TESTING
中定义,它允许控制是否构建项目的所有测试。
只有在调用
enable_testing()
命令时,CMake才会生成测试。当CTest
选项为BUILD_TESTING
时,ON
模块会自动调用该命令。
以上内容可在CLI上使用,如下所示:
创建测试(默认):
cmake -Hexample-testing -B_builds/example-testing/release -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Release
cmake --build _builds/example-testing/release --config Release
在这种情况下,命令cd _builds/example-testing/release
和ctest
/ cmake --build . --target test
构建和运行测试。
不要创建测试:
cmake -Hexample-testing -B_builds/example-testing/release-no-tests -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF
cmake --build _builds/example-testing/release-no-tests --config Release
在这种情况下,命令cd _builds/example-testing/release-no-tests
和ctest
不运行任何测试,因为没有构建测试。
命令cmake --build . --target test
失败,因为在CMake的配置阶段尚未创建。
我们只是在这里搔痒。请参阅ctest --help
,例如有很多--build-<...>
选项可以更好地控制测试/构建,但我没有任何经验。
我强烈建议您阅读以下内容:
如果您确实想要启用测试的构建,但是通过默认情况下未调用的单独目标并且不是通过CTest运行测试,而是直接执行以下操作:
include(CTest)
if(BUILD_TESTING)
find_package(GTest MODULE REQUIRED)
option(
BUILD_TESTING_EXCLUDE_FROM_ALL
"Do not build the testing tree together with the default build target."
OFF
)
if(BUILD_TESTING_EXCLUDE_FROM_ALL)
set(add_executable_args_for_test EXCLUDE_FROM_ALL)
endif()
# The "build_test" target is used to build all test executables.
add_custom_target(
build_test
# Workaround for printing the COMMENT, it does not work without a NOOP
# COMMAND.
COMMAND ${CMAKE_COMMAND} -E echo
COMMENT "Building tests..."
VERBATIM
)
add_executable(example_test ${add_executable_args_for_test} example_test.cpp)
target_link_libraries(
example_test
PRIVATE
GTest::GTest
GTest::Main
)
add_test(NAME example_test COMMAND example_test)
add_dependencies(build_test example_test)
# The "check" target is used to build AND run all test executables.
add_custom_target(
check
# Either invoke the test(s) indirectly via "CTest" (commented) or directly.
# COMMAND ${CMAKE_CTEST_COMMAND}
COMMAND example_test
COMMENT "Building and running test..."
VERBATIM
)
# Alternative to the COMMAND in the add_custom_target. Leads to the same
# behavior as calling "CTest" directly.
# add_custom_command(
# TARGET check
# COMMAND ${CMAKE_COMMAND} ARGS --build ${CMAKE_BINARY_DIR} --target test
# VERBATIM
# )
add_dependencies(check build_test)
endif()
test
来运行测试,而是直接测试。恕我直言,Kitware应删除整个CMake Wiki ,因为Wiki几乎只包含CMake版本的过时信息&lt; 3.0。其中的大多数信息都不能被视为 Modern CMake 。