Unit testing as part of the build

See a similar problem and my answer here.

Mainly my recommendation is to add a POST_BUILD step to your unit test targets that runs ctest. If a POST_BUILD step does fail (return code is not 0), the build will fail.

Something like:

set(UNIT_TEST MyLibUnitTestTargetName)
add_test(NAME ${UNIT_TEST} COMMAND ${UNIT_TEST})
add_custom_command(
     TARGET ${UNIT_TEST}
     COMMENT "Run tests"
     POST_BUILD 
     WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
     COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> -R "^${UNIT_TEST}$" --output-on-failures
)

This has the advantage that it runs like you would call ctest.

The short version - without add_test() / ctest - would be:

set(UNIT_TEST MyLibUnitTestTargetName)
add_custom_command(
     TARGET ${UNIT_TEST}
     COMMENT "Run tests"
     POST_BUILD 
     COMMAND ${UNIT_TEST}
)

References:

  • add_test()
  • add_custom_command()
  • How to run ctest after building my project with cmake
  • CMake: Running unit test as part of the build

If you want your test binary to be preserved, even if tests fail, you can try something like this:

set(UNIT_TEST MyLibUnitTestTargetName)
add_test(NAME ${UNIT_TEST} COMMAND ${UNIT_TEST})
add_custom_target(run_unit_test ALL
    COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
    DEPENDS ${UNIT_TEST})

This will create a target that always runs your unit tests. However, because it's a separate target failure of that command will result in build failure, but not in removing the binary produced by your original UNIT_TEST target.