2016-08-23 48 views
2

我們有幾個單元測試,我們希望作爲構建過程的一部分運行。CMake - 運行測試作爲構建過程的一部分,並將stdout輸出捕獲到文件中

爲了達到這個目的,我有一個助手腳本,它創建一個運行測試的自定義命令,如果成功,創建一個文件"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捕獲到文件中,當退出狀態爲錯誤時,將該文件捕獲。

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,那就這樣吧。

+1

爲什麼不使用ctest和cmake的集成? – fghj

+0

@ user1034749 AFAIK ctest不會將測試作爲構建的一部分運行。這是一個單獨的目標'make test'。我以前使用ctest來運行每個測試('COMMAND ctest --build-config $ --tests-regex $ {TEST_NAME} --output-on-failure'),但通過ctest調用每個單元測試都會大大增加編譯時間 –

+0

@ user1034749更新了我與ctest有關的問題,以及爲什麼我要尋找替代方法 –

回答

0

回答我自己的問題,因爲我找到了適合我的解決方案。

在下面的摘錄中,${ARG_NAME}是我們構建並希望運行的測試二進制文件。

有同時運行測試創建2個文件

  • ${ARG_NAME}.output其中包含測試輸出
  • ${ARG_NAME}.passed這是創建一個哨兵文件,如果測試成功

custom_command由幾個命令,而且我們依賴於cmake在其中一個失敗時會立即停止執行的事實。

我們運行測試:

${ARG_NAME} 

所有的測試輸出重定向到${ARG_NAME}.output,所以當測試通過

${ARG_NAME} >> ${OUTPUT_FILE} 2>&1 

使用測試的退出狀態,在我們不污染標準輸出發生故障時,我們捕獲文件:

${ARG_NAME} >> ${OUTPUT_FILE} 2>&1 || cat ${OUTPUT_FILE} 

但是,只有當測試通過d ·我們要創建的定點文件,所以我們貓的文件並運行false

${ARG_NAME} >> ${OUTPUT_FILE} 2>&1 || (cat ${OUTPUT_FILE} && false) 

如果測試通過(退出狀態0),那麼我們將不會運行cat output && false,所以後來接下來cmake的命令運行

${CMAKE_COMMAND} -E touch ${PASSED_FILE} 

最後,我們創建一個custom_target依賴於.passed文件

set(OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/${ARG_NAME}.output) 
set(PASSED_FILE ${CMAKE_CURRENT_BINARY_DIR}/${ARG_NAME}.passed) 

# create test.passed command which runs this test and creates a sentinel file 
# if it passes 
add_custom_command(
    OUTPUT 
     ${PASSED_FILE} 

    COMMAND 
     ${CMAKE_CURRENT_BINARY_DIR}/${ARG_NAME} >> ${OUTPUT_FILE} 2>&1 
       || (cat ${OUTPUT_FILE} && false) 

    COMMAND 
     ${CMAKE_COMMAND} -E touch ${PASSED_FILE} 

    COMMENT 
     "Running ${ARG_NAME} tests" 

    DEPENDS 
     ${ARG_NAME} 

    USES_TERMINAL 
    ) 

# create test.run target which depends on test.passed 
add_custom_target(${ARG_NAME}.run 
    ALL 
    DEPENDS ${PASSED_FILE} 
    ) 
1

問題是,沒有標準的方法將輸出從通過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.inexecute_process運行測試可執行文件和錯誤輸出重定向到一個日誌文件的模板測試運行腳本:

set (_testExecutable "${CMAKE_ARGV3}") 
execute_process(COMMAND ${_testExecutable} ERROR_FILE "@[email protected]" RESULT_VARIABLE _testResult) 
if (_testResult) 
    file(REMOVE "@[email protected]") 
    file(READ "@[email protected]" _contents) 
    message (STATUS "${_contents}") 
else() 
    file(WRITE "@[email protected]" "") 
endif() 

如果測試失敗,該腳本刪除定點文件,輸出錯誤日誌。 如果測試成功,腳本將創建標識文件。

相關問題