gpt4 book ai didi

unit-testing - CMake - 在构建过程中运行测试并将标准输出捕获到文件

转载 作者:行者123 更新时间:2023-12-05 06:41:52 25 4
gpt4 key购买 nike

我们有几个单元测试,我们希望将其作为构建过程的一部分运行。

为了实现这一点,我有一个帮助程序脚本,它创建一个运行测试的自定义命令,如果成功,则创建一个文件 "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 脚本语法 - 将 stdout 捕获到文件中,当退出状态为错误时,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}
)

这样做的问题有两个。

  1. 大大增加了构建时间。每个测试都必须通过单独的 ctest 进程执行,所有已注册的测试名称都根据正则表达式进行解析,等等。随着单个测试的数量增加,我们的额外时间会增加很多。
  2. ctest 默认输出大量噪音。指定 --quiet 标志会抑制 --output-on-failure 标志,因此您可能有嘈杂的输出或没有输出 - 没有办法只获得失败。

问题

有没有办法实现我想要的?

即:

  • 手动运行测试(即:不通过 ctest)
  • 将输出捕获到文件
  • 仅在测试退出状态指示失败时才输出该文件。
  • 在测试退出状态指示成功的情况下触摸哨兵文件。

跨平台方法的加分点,但如果它必须仅限于 Linux,那就这样吧。

最佳答案

问题是没有标准的方法可以将通过 add_custom_command 调用的命令的输出重定向到文件。然而,CMake 命令 execute_process 确实具有该功能。

因此,一种可能的解决方案是从配置的 CMake 脚本运行测试可执行文件,该脚本本身作为 CMake 自定义命令运行。以下代码概述了必要的步骤:

在添加测试的 CMakeLists.txt 中,配置 CMake 脚本模板:

configure_file("test_runner.cmake.in" "test_runner_${TEST_NAME}.cmake" @ONLY)

然后添加自定义命令以在构建时调用脚本:

add_custom_command(
OUTPUT ${TEST_NAME}.passed
COMMAND ${CMAKE_COMMAND} -P "test_runner_${TEST_NAME}.cmake" $<TARGET_FILE:${TEST_NAME}>
DEPENDS ${TEST_NAME}
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")

测试可执行文件的实际路径通过生成器表达式作为参数传递给脚本。

模板测试运行器脚本 test_runner.cmake.in 使用 execute_process 运行测试可执行文件并将错误输出重定向到日志文件:

set (_testExecutable "${CMAKE_ARGV3}")
execute_process(COMMAND ${_testExecutable} ERROR_FILE "@TEST_NAME@.output" RESULT_VARIABLE _testResult)
if (_testResult)
file(REMOVE "@TEST_NAME@.passed")
file(READ "@TEST_NAME@.output" _contents)
message (STATUS "${_contents}")
else()
file(WRITE "@TEST_NAME@.passed" "")
endif()

如果测试失败,脚本会删除哨兵文件并输出错误日志。如果测试成功,脚本会创建哨兵文件。

关于unit-testing - CMake - 在构建过程中运行测试并将标准输出捕获到文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39105210/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com