102

我正在 CMake 中尝试 CTest,以便使用make test目标自动运行我的一些测试。问题是 CMake 不“理解”我愿意运行的测试必须构建,因为它是项目的一部分。

所以我正在寻找一种明确指定这种依赖关系的方法。

4

11 回答 11

90

可以说这是CMake 中的一个错误(以前在此处跟踪),这不能开箱即用。一种解决方法是执行以下操作:

add_test(TestName ExeName)
add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}
                  DEPENDS ExeName)

然后你可以运行make check它,它将编译并运行测试。如果您有多个测试,那么您将不得不DEPENDS exe1 exe2 exe3 ...在上面的行中使用。

于 2009-04-10T05:57:33.937 回答
57

其实是有办法使用的make test。您需要将测试可执行文件的构建定义为测试之一,然后在测试之间添加依赖关系。那是:

ADD_TEST(ctest_build_test_code
         "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target test_code)
ADD_TEST(ctest_run_test_code test_code)
SET_TESTS_PROPERTIES(ctest_run_test_code
                     PROPERTIES DEPENDS ctest_build_test_code)
于 2012-05-30T21:32:46.040 回答
15

我使用richq 答案的变体。在顶层CMakeLists.txt,我添加了一个自定义目标build_and_test,用于构建和运行所有测试:

find_package(GTest)
if (GTEST_FOUND)
    enable_testing()
    add_custom_target(build_and_test ${CMAKE_CTEST_COMMAND} -V)
    add_subdirectory(test)
endif()

在下的各种子项目CMakeLists.txt文件中test/,我将每个测试可执行文件添加为以下依赖项build_and_test

include_directories(${CMAKE_SOURCE_DIR}/src/proj1)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(proj1_test proj1_test.cpp)
target_link_libraries(proj1_test ${GTEST_BOTH_LIBRARIES} pthread)
add_test(proj1_test proj1_test)
add_dependencies(build_and_test proj1_test)

使用这种方法,我只需要make build_and_test代替make test(或make all test),它的好处是只构建测试代码(及其依赖项)。很遗憾我不能使用目标名称test。就我而言,这还不错,因为我有一个顶级脚本,它通过调用cmake然后进行树外调试和发布(和交叉编译)构建make,并将其转换testbuild_and_test.

显然,不需要 GTest 的东西。我只是碰巧使用/喜欢 Google Test,并想分享一个使用 CMake/CTest 的完整示例。恕我直言,这种方法还具有允许我使用的好处ctest -V,它在测试运行时显示 Google Test 输出:

1: Running main() from gtest_main.cc
1: [==========] Running 1 test from 1 test case.
1: [----------] Global test environment set-up.
1: [----------] 1 test from proj1
1: [ RUN      ] proj1.dummy
1: [       OK ] proj1.dummy (0 ms)
1: [----------] 1 test from proj1 (1 ms total)
1:
1: [----------] Global test environment tear-down
1: [==========] 1 test from 1 test case ran. (1 ms total)
1: [  PASSED  ] 1 test.
1/2 Test #1: proj1_test .......................   Passed    0.03 sec
于 2013-02-25T05:53:52.080 回答
8

如果您使用 CMake >= 3.7,那么推荐的方法是使用fixtures

add_executable(test test.cpp)
add_test(test_build
  "${CMAKE_COMMAND}"
  --build "${CMAKE_BINARY_DIR}"
  --config "$<CONFIG>"
  --target test
)
set_tests_properties(test_build PROPERTIES FIXTURES_SETUP    test_fixture)
add_test(test test)
set_tests_properties(test       PROPERTIES FIXTURES_REQUIRED test_fixture)

这将执行以下操作:

  • 添加一个test从构建的可执行目标test.cpp
  • 添加一个test_build运行 Cmake 来构建目标的“测试”test
  • 将测试标记test_build为夹具的设置任务test_fixture
  • 添加一个test只运行test可执行文件的测试
  • 标记test测试需要fixture test_fixture

因此,每次test运行 test 时,它首先运行 test test_build,它会构建必要的可执行文件。

于 2019-06-04T17:09:23.743 回答
7

如果您尝试模拟make check,您可能会发现此 wiki 条目很有用:

http://www.cmake.org/Wiki/CMakeEmulateMakeCheck

我刚刚检查过它是否成功(CMake 2.8.10)。

于 2013-03-12T16:08:28.110 回答
6

免得自己头疼:

make all test

对我来说开箱即用,并将在运行测试之前构建依赖项。鉴于这是多么简单,它几乎使本机make test功能变得方便,因为它使您可以选择运行最后的编译测试,即使您的代码已损坏。

于 2015-04-04T08:48:26.030 回答
2

这是我敲定并一直在使用的:

set(${PROJECT_NAME}_TESTS a b c)

enable_testing()
add_custom_target(all_tests)
foreach(test ${${PROJECT_NAME}_TESTS})
        add_executable(${test} EXCLUDE_FROM_ALL ${test}.cc)
        add_test(NAME ${test} COMMAND $<TARGET_FILE:${test}>)
        add_dependencies(all_tests ${test})
endforeach(test)

build_command(CTEST_CUSTOM_PRE_TEST TARGET all_tests)
string(CONFIGURE \"@CTEST_CUSTOM_PRE_TEST@\" CTEST_CUSTOM_PRE_TEST_QUOTED ESCAPE_QUOTES)
file(WRITE "${CMAKE_BINARY_DIR}/CTestCustom.cmake" "set(CTEST_CUSTOM_PRE_TEST ${CTEST_CUSTOM_PRE_TEST_QUOTED})" "\n")

YMMV

于 2018-12-20T21:57:18.720 回答
2

对于 CMake 3.10 或更高版本,另一种选择是使用TEST_INCLUDE_FILES目录属性设置脚本,在运行测试之前触发构建。在最外层CMakeLists.txt添加以下代码:

set_property(DIRECTORY APPEND
    PROPERTY TEST_INCLUDE_FILES "${CMAKE_CURRENT_BINARY_DIR}/BuildTestTarget.cmake")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/BuildTestTarget.cmake"
   "execute_process(COMMAND \"${CMAKE_COMMAND}\""
   " --build \"${CMAKE_BINARY_DIR}\""
   " --config \"\$ENV{CMAKE_CONFIG_TYPE}\")")

实际的测试配置通过环境变量传递给构建CMAKE_CONFIG_TYPE。或者,您可以添加一个--target选项以仅构建测试所需的目标。

于 2021-04-24T18:27:15.550 回答
1

井架的回答,简化和评论:

# It is impossible to make target "test" depend on "all":
# https://gitlab.kitware.com/cmake/cmake/-/issues/8774
# Set a magic variable in a magic file that tells ctest
# to invoke the generator once before running the tests:
file(WRITE "${CMAKE_BINARY_DIR}/CTestCustom.cmake"
    "set(CTEST_CUSTOM_PRE_TEST ${CMAKE_MAKE_PROGRAM})\n"
)

这并不完全正确,因为它不能解决 running 的并发问题ninja all test,以防万一有人这样做。相反,因为现在,你有两个忍者进程。

(Ftr,我也在这里分享了这个解决方案。)

于 2020-09-03T22:24:18.963 回答
-4

以上所有答案都是完美的。但实际上 CMake 使用 CTest 作为其测试工具,因此执行任务的标准方法(我认为是)是:

enable_testing ()
add_test (TestName TestCommand)
add_test (TestName2 AnotherTestCommand)

然后运行​​cmakemake来构建目标。之后,您可以运行make test,或者只运行

ctest

你会得到结果。这是在 CMake 2.8 下测试的。

检查详细信息:http ://cmake.org/Wiki/CMake/Testing_With_CTest#Simple_Testing

于 2012-08-24T14:20:11.553 回答
-5

所有的答案都很好,但它们暗示了通过命令运行测试的传统违反make test。我已经完成了这个技巧:

add_test(NAME <mytest>
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMAND sh -c "make <mytarget>; $<TARGET_FILE:<mytarget>>")

这意味着测试包括构建(可选)和运行可执行目标。

于 2013-05-20T13:25:12.803 回答