我们有几个单元测试,我们希望将其作为构建过程的一部分运行。
为了实现这一目标,我有一个帮助程序脚本,它创建一个运行测试的自定义命令,如果成功,则创建一个文件"test_name.passed"
.
然后我添加一个自定义目标"test_name.run"
这取决于"test_name.passed"
.
这个想法是如果"test_name.passed"
不存在或早于"test_name"
,将运行自定义命令。
构建将继续运行自定义命令,直到测试通过。一旦通过,后续构建将不会调用自定义命令,因此不需要时不会运行测试。
到目前为止,这一切都与描述的完全一样
这是脚本:
# create command which runs the test and creates a sentinel file if it passes
add_custom_command(
OUTPUT ${TEST_NAME}.passed
COMMAND $<TARGET_FILE:${TEST_NAME}>
COMMAND ${CMAKE_COMMAND} -E touch ${TEST_NAME}.passed
DEPENDS ${TEST_NAME}
)
# create test.run module which depends on test.passed
add_custom_target(${TEST_NAME}.run
ALL
DEPENDS ${TEST_NAME}.passed
)
问题——噪音stdout
问题是我们的测试经常记录大量信息stdout
,这会导致构建非常嘈杂。
我现在正在尝试捕捉stdout
到文件,并且仅在发生故障时才显示测试输出。
我的第一次尝试是尝试 Bash shell 脚本语法 - capturestdout
到一个文件中,当退出状态为错误时,cat 该文件。
add_custom_command(
OUTPUT ${TEST_NAME}.passed
COMMAND $<TARGET_FILE:${TEST_NAME}> > ${TEST_NAME}.output || cat ${TEST_NAME}.output
COMMAND ${CMAKE_COMMAND} -E touch ${TEST_NAME}.passed
DEPENDS ${TEST_NAME}
)
这不起作用,因为即使测试失败我也会得到哨兵"test_name.passed"
创建文件,这意味着下次我尝试构建它时认为测试通过了。
可能不符合标准的修复
通过集成ctest
,我可以通过 ctest 运行每个测试并使用命令行选项--output-on-failure
add_custom_command(
OUTPUT ${TEST_NAME}.passed
COMMAND ctest --build-config $<CONFIGURATION> --tests-regex ${TEST_NAME} --output-on-failure
COMMAND ${CMAKE_COMMAND} -E touch ${TEST_NAME}.passed
DEPENDS ${TEST_NAME}
)
这样做的问题有两个。
- It vastly增加构建时间。每个测试都必须通过单独的 ctest 进程执行,所有注册的测试名称都根据正则表达式进行解析,等等。随着单独测试的数量增加,我们的额外时间会增加很多。
- ctest 默认输出大量噪声。指定
--quiet
标志抑制--output-on-failure
标志,因此您可以有嘈杂的输出或没有输出 - 没有办法只得到失败。
Question
有办法实现我想要的吗?
ie:
- 手动运行测试(即:不通过 ctest)
- 将输出捕获到文件中
- 仅在测试退出状态指示失败时输出该文件。
- 如果测试退出状态指示成功,请触摸哨兵文件。
跨平台方法的优点是,但如果它只能是 Linux,那就这样吧。