34

I want my tests to be launched each time my project is successfully built. And if some tests are broken I want my build to be broken too. By default I need to run tests manually by running ctest command. CTest can actually build project but I use IDE that invokes make to build sources. And make doesn't run tests.

I add this command to my root CMakeLists.txt file but it doesn't work.

add_custom_command(OUTPUT tests.txt 
                   POST_BUILD
                   COMMAND ctest --output-on-failure)

CMake doesn't return any errors and everything builds fine but my custom command doesn't invokes. How can I run something after each successful build in CMake?

Update:

My final solution is creating this macro:

macro(add_unit_test target target_test)
    set(UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} ${target_test} PARENT_SCOPE)
    add_test(target ${CMAKE_CURRENT_BINARY_DIR}/${target_test})
endmacro(add_unit_test)

It calls add_test and remembers test target in a list. Every test in a project added by this macro. In the root CMakeLists.txt I have this code:

add_custom_target( all_tests ALL
                   DEPENDS ${UNIT_TEST_TARGETS}
)
add_custom_command(TARGET all_tests
                   COMMENT "Run tests"
                   POST_BUILD COMMAND ctest ARGS --output-on-failure
                   WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)

It creates custom target that depends on all unit tests in a project. Custom command is runs after all_tests target was built.

user1902689
  • 1,655
  • 2
  • 22
  • 33
Evgeny Lazin
  • 9,193
  • 6
  • 47
  • 83
  • 2
    Thanks for the answer - in your macro, in `add_test`, I think you need `${target_test}` instead of `target_test` – experquisite Mar 08 '16 at 16:25
  • What did you mean in your comment on the answer, regarding your "Update" section here, regarding avoiding running "stale tests"? At first, I thought you came up with a way to only run tests that were newly built. But, I now see this runs `ctest` on all tests. – user1902689 May 13 '19 at 04:07

1 Answers1

29

This form of add_custom_command will only execute if another CMake target has a dependency on "tests.txt". I assume that no other target has "tests.txt" as an input file, hence the custom command never runs.

I think you could use the second form of add_custom_command to achieve your goal; something like:

add_custom_command(TARGET MainTest
                   POST_BUILD
                   COMMAND ctest -C $<CONFIGURATION> --output-on-failure)
Fraser
  • 74,704
  • 20
  • 238
  • 215
  • 2
    Thanks for answer, appreciate this! I found similar solution. I create custom target that depends on every unit test in the project and than I use `add_custom_command` with my custom target as a TARGET parameter. This is essential because I don't want to run stale tests. And I also discover that it is impossible to enumerate all the targets in the `cmake` project so list of targets need to be maintained manually. – Evgeny Lazin Feb 28 '13 at 06:29
  • I have a question regarding running test. Currently I have an `sh`-script building the project in a separate build directory. Is it common to add `ctest` invokation in the script after `cmake . && make` is done? – St.Antario Mar 30 '19 at 08:48
  • A bit buggy example. $ may be not set. In this case `--output-on-failure` will become an argument for `-C`. – loshad vtapkah Dec 28 '19 at 22:34