[CMake] Running unit test as part of the build

Michael Wild themiwi at gmail.com
Tue Sep 13 05:05:07 EDT 2011


On 09/12/2011 09:06 PM, Erik Johansson wrote:
> On Mon, Sep 12, 2011 at 20:30, Michael Wild <themiwi at gmail.com> wrote:
>> How about using a custom command that runs the unit test using a
>> wrapper script that upon successful completion creates a stamp-file and
>> depends upon the unit-test executable target itself?
> 
> This seems to work:
> 
> add_executable(unittest ${test_SRCS})
> 
> set(unittest_stamp
>   "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/unittest.stamp")
> add_custom_command(OUTPUT "${unittest_stamp}"
>   COMMAND ${CMAKE_CTEST_COMMAND} $(ARGS)
>   COMMAND ${CMAKE_COMMAND} -E touch "${unittest_stamp}"
>   COMMENT "Running unit test"
>   DEPENDS unittest)
> add_custom_target(unittest_run ALL DEPENDS "${unittest_stamp}")
> 
> // Erik
> 

I think the OP wanted to run the tests individually, so I don't think
you should be using CMAKE_CTEST_COMMAND, but rather the unittest
executable directly, such that only tests that failed or where the test
executable changed are re-run.


E.g.:

###################################################################
cmake_minimum_required(VERSION 2.8)
project(tests CXX)

# usually one would put this in a proper file, not WRITE it like this
file(WRITE ${CMAKE_BINARY_DIR}/run_test.cmake "
if(NOT EXISTS \${TEST_EXE})
  message(FATAL_ERROR \"'\${TEST_EXE}' does not exist\")
endif()
execute_process(COMMAND \${TEST_EXE}
  RESULT_VARIABLE result)
if(result)
  message(\"\${TEST_NAME} failed\")
else()
  execute_process(COMMAND \${CMAKE_COMMAND} -E touch \${TEST_STAMP})
endif()
")

# create some tests, number 2 fails
file(WRITE ${CMAKE_BINARY_DIR}/test.cpp.in "
// need to sleep a bit for the time stamps to work...
#include <unistd.h>
int main() {sleep(1); return @exit_status@;}
")
foreach(i RANGE 1 3)
  if(i EQUAL 2)
    set(exit_status 1)
  else()
    set(exit_status 0)
  endif()
  configure_file(${CMAKE_BINARY_DIR}/test.cpp.in
    ${CMAKE_BINARY_DIR}/test${i}.cpp @ONLY)
endforeach()

add_custom_target(alltests ALL)
foreach(t test1 test2 test3)
  add_executable(unit${t} ${CMAKE_BINARY_DIR}/${t}.cpp)
  set(stamp
    "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/unit${t}.stamp")
  add_custom_command(OUTPUT "${stamp}"
    COMMAND ${CMAKE_COMMAND} -DTEST_NAME=${t}
      -DTEST_EXE=$<TARGET_FILE:unit${t}> -DTEST_STAMP=${stamp}
      -P ${CMAKE_BINARY_DIR}/run_test.cmake
    COMMENT "Running unit test ${t}"
    DEPENDS unit${t})
  add_custom_target(run_${t} ALL DEPENDS "${stamp}")
  add_dependencies(alltests run_${t})
endforeach()
###################################################################

HTH

Michael


More information about the CMake mailing list