【问题标题】:Expected build-failure tests in CMakeCMake 中的预期构建失败测试
【发布时间】:2015-05-10 19:14:54
【问题描述】:

有时最好检查某些东西是否无法构建,例如:

// 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();

是否可以将这些类型的东西合并到 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)

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

【问题讨论】:

  • 请注意,您的具体示例可以使用static_assert(!std::is_convertible_v<container::const_iterator, container::iterator> and !std::is_constructible_v<container::iterator, container::const_iterator>); 直接在 C++ 中进行测试,测试隐式和显式转换均失败。如果成员类型不存在,这具有正确失败测试的优势。

标签: c++ cmake automated-tests ctest


【解决方案1】:

您可以或多或少地按照您的描述执行此操作。您可以添加一个编译失败的目标,然后添加一个调用cmake --build 的测试来尝试构建目标。剩下的就是将测试属性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

然后你可以在你的 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)

如果你有很多这些要写的话,你显然可以将所有这些包装到一个函数或宏中。

【讨论】:

  • 请问你是怎么知道这些东西的?我喜欢 cmake,但相对于其他构建系统,我从来没有找到一个全面的在线教程。
  • 主要在中型代码库中使用 CMake,遵循邮件列表,并尝试回答 StackOverflow 问题 :) 文档现在非常好,并且正在改进,尽管 CTest 的文档是方式在我看来,落后于 CMake。
  • 不错。请注意,如果我们想检查一个精确的错误(比如静态断言失败的结果),我们可以设置测试属性:PASS_REGULAR_EXPRESSIONWILL_FAIL不能同时使用。
  • 小心。如果您的程序崩溃或调用中止,则 WILL_FAIL 选项不会按预期工作。这意味着,例如使用 munit (nemequ.github.io/munit) 的失败断言即使使用 WILL_FAIL 仍然会使您的测试失败。
【解决方案2】:

@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)

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

【讨论】:

  • 只是想提一下,如果您想将迷你项目中的多个测试用例分组到主项目中的单个测试中,这也非常有用。您可能还想设置--build-config $&lt;CONFIGURATION&gt;
猜你喜欢
  • 1970-01-01
  • 2013-01-30
  • 2018-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-04
  • 2019-10-02
相关资源
最近更新 更多