在CMake中预期的构建失败测试

Ami*_*ory 32 c++ automated-tests cmake ctest

有时检查某些事情是否无法构建是很好的,例如:

// Next line should fail to compile: can't convert const iterator to iterator.
my_new_container_type::iterator it = my_new_container_type::const_iterator();
Run Code Online (Sandbox Code Playgroud)

是否可以将这些类型的东西合并到CMake/CTest中?我正在寻找这样的东西CMakeLists.txt:

add_build_failure_executable(
    test_iterator_conversion_build_failure
    iterator_conversion_build_failure.cpp)
add_build_failure_test(
    test_iterator_conversion_build_failure
    test_iterator_conversion_build_failure)
Run Code Online (Sandbox Code Playgroud)

(当然,据我所知,这些特定的CMake指令不存在.)

Fra*_*ser 34

你可以或多或少地按照你的描述做到这一点.您可以添加无法编译的目标,然后添加一个调用cmake --build以尝试构建目标的测试.剩下的就是将test属性设置WILL_FAIL为true.

所以,假设您在名为"will_fail.cpp"的文件中进行了测试,该文件包含:

#if defined TEST1
non-compiling code for test 1
#elif defined TEST2
non-compiling code for test 2
#endif
Run Code Online (Sandbox Code Playgroud)

然后,您可以在CMakeLists.txt中使用以下内容:

cmake_minimum_required(VERSION 3.0)
project(Example)

include(CTest)

# Add a couple of failing-to-compile targets
add_executable(will_fail will_fail.cpp)
add_executable(will_fail_again will_fail.cpp)
# Avoid building these targets normally
set_target_properties(will_fail will_fail_again PROPERTIES
                      EXCLUDE_FROM_ALL TRUE
                      EXCLUDE_FROM_DEFAULT_BUILD TRUE)
# Provide a PP definition to target the appropriate part of
# "will_fail.cpp", or provide separate files per test.
target_compile_definitions(will_fail PRIVATE TEST1)
target_compile_definitions(will_fail_again PRIVATE TEST2)

# Add the tests.  These invoke "cmake --build ..." which is a
# cross-platform way of building the given target.
add_test(NAME Test1
         COMMAND ${CMAKE_COMMAND} --build . --target will_fail --config $<CONFIGURATION>
         WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME Test2
         COMMAND ${CMAKE_COMMAND} --build . --target will_fail_again --config $<CONFIGURATION>
         WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# Expect these tests to fail (i.e. cmake --build should return
# a non-zero value)
set_tests_properties(Test1 Test2 PROPERTIES WILL_FAIL TRUE)
Run Code Online (Sandbox Code Playgroud)

如果要编写很多这些函数或宏,显然可以将所有这些包装成函数或宏.

  • 尼斯.注意,如果我们想检查一个精确的错误(比如静态断言失败导致的错误),我们可以设置test属性:`PASS_REGULAR_EXPRESSION`.`WILL_FAIL`不得同时使用. (3认同)

Cra*_*ott 6

@Fraser的答案是一个很好的方法,特别是该WILL_FAIL属性是一个很好的建议。但是,还有一种方法可以使失败的目标成为主项目的一部分。问题中的用例几乎就是该ctest --build-and-test模式的含义。您可以将其放入其自己的单独迷你项目中,然后将其作为测试的一部分,而不是将预期失败的目标纳入主版本。在主项目中可能看起来像这样的一个例子是这样的:

add_test(NAME iter_conversion
    COMMAND ${CMAKE_CTEST_COMMAND}
            --build-and-test
                ${CMAKE_CURRENT_LIST_DIR}/test_iter
                ${CMAKE_CURRENT_BINARY_DIR}/test_iter
            --build-generator ${CMAKE_GENERATOR}
            --test-command ${CMAKE_CTEST_COMMAND}
)
set_tests_properties(iter_conversion PROPERTIES WILL_FAIL TRUE)
Run Code Online (Sandbox Code Playgroud)

这样做的好处是它将成为项目测试结果的一部分,因此更有可能在正常测试过程中定期执行。在上面的示例中,test_iter目录实质上是它自己的单独项目。如果您需要从主版本传递信息,则可以通过添加--build-options以定义要传递给CMake运行的缓存变量来实现。查看最新文档,以获取有关此区域的最近更正/澄清的帮助。