Skip to content

Instantly share code, notes, and snippets.

@WardBrian
Last active September 22, 2025 03:49
Show Gist options
  • Save WardBrian/1932c302fca3f9bf46563bf7a0666af9 to your computer and use it in GitHub Desktop.
Save WardBrian/1932c302fca3f9bf46563bf7a0666af9 to your computer and use it in GitHub Desktop.
CTest registration for Boost.UT. License: BSD-3-Clause
FetchContent_Declare(boost_ut
GIT_REPOSITORY https://github.com/boost-ext/ut.git
GIT_TAG v2.3.1)
FetchContent_MakeAvailable(boost_ut)
# link this object to your test executable, then call discover_boost_ut_test() on it
add_library(boost_ut_runner OBJECT test_runner.cpp)
target_link_libraries(boost_ut_runner PUBLIC Boost::ut)
# Based on https://gitlab.kitware.com/cmake/cmake/-/blob/master/Modules/GoogleTest.cmake#L545
# This defines a function that is an alternative to add_test()
# that adds each individual test in the executable as its own ctest test
# A nice overview of this feature is described here: https://www.kitware.com/dynamic-google-test-discovery-in-cmake-3-10/
function (discover_boost_ut_test TARGET)
set(ctest_file_base "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}")
set(ctest_include_file "${ctest_file_base}_include.cmake")
set(ctest_tests_file "${ctest_file_base}_tests.cmake")
file(WRITE "${ctest_include_file}"
"if(EXISTS \"${ctest_tests_file}\")\n"
" include(\"${ctest_tests_file}\")\n"
"else()\n"
" add_test(${TARGET}_NOT_BUILT ${TARGET}_NOT_BUILT)\n"
"endif()\n"
)
add_custom_command(
TARGET ${TARGET} POST_BUILD
BYPRODUCTS "${ctest_tests_file}"
COMMAND "${CMAKE_COMMAND}"
-D "TEST_TARGET=${TARGET}"
-D "TEST_EXECUTABLE=$<TARGET_FILE:${TARGET}>"
-D "CTEST_FILE=${ctest_tests_file}"
-P "${_UT_DISCOVER_TESTS_SCRIPT}"
VERBATIM
)
# Add discovered tests to directory TEST_INCLUDE_FILES
set_property(DIRECTORY
APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}"
)
endfunction()
set(_UT_DISCOVER_TESTS_SCRIPT
${CMAKE_CURRENT_LIST_DIR}/BoostUTAddTests.cmake
)
# based on https://gitlab.kitware.com/cmake/cmake/-/blob/master/Modules/GoogleTestAddTests.cmake?ref_type=heads
# this file defines a script that lists all the tests in a given executable
# and adds each one individually as a ctest test
# A nice overview of this feature is described here: https://www.kitware.com/dynamic-google-test-discovery-in-cmake-3-10/
set(script)
set(suite)
set(tests)
function(add_command NAME)
set(_args "")
foreach(_arg ${ARGN})
if(_arg MATCHES "[^-./:a-zA-Z0-9_]")
set(_args "${_args} [==[${_arg}]==]")
else()
set(_args "${_args} ${_arg}")
endif()
endforeach()
set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE)
endfunction()
# Run test executable to get list of available tests
if(NOT EXISTS "${TEST_EXECUTABLE}")
message(FATAL_ERROR
"Specified test executable '${TEST_EXECUTABLE}' does not exist"
)
endif()
execute_process(
COMMAND "${TEST_EXECUTABLE}" --list-test-names-only --use-colour no
OUTPUT_VARIABLE output
RESULT_VARIABLE result
)
if(NOT ${result} EQUAL 0)
message(FATAL_ERROR
"Error running test executable '${TEST_EXECUTABLE}':\n"
" Result: ${result}\n"
" Output: ${output}\n"
)
endif()
string(REPLACE "\n" ";" output "${output}")
foreach(test ${output})
if (test MATCHES "^Suite '")
continue() # Skip suite names
endif()
add_command(add_test
"${TEST_TARGET}:${test}"
"${TEST_EXECUTABLE}"
"${test}"
"--success"
"--durations"
)
message(CONFIGURE_LOG "Discovered test: ${TEST_TARGET}:${test}")
list(APPEND tests "${test}")
endforeach()
# Create a list of all discovered tests, which users may use to e.g. set
# properties on the tests
add_command(set ${TEST_LIST} ${tests})
# Write CTest script
file(WRITE "${CTEST_FILE}" "${script}")
#include <boost/ut.hpp>
int main(int argc, const char* argv[]) {
namespace ut = boost::ut;
return ut::cfg<ut::override>.run({.argc = argc, .argv = argv});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment