Skip to content
Draft
85 changes: 85 additions & 0 deletions tests/CMake/BoostUT.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
FetchContent_Declare(boost_ut
GIT_REPOSITORY https://github.com/boost-ext/ut.git
GIT_TAG v2.3.1)
FetchContent_MakeAvailable(boost_ut)



# this target builds an executable that contains all the tests
# this can be faster than building each separately for local development
add_executable(jumbo_test EXCLUDE_FROM_ALL test_runner.cpp)
set_target_properties(jumbo_test PROPERTIES
CXX_STANDARD 20
UNITY_BUILD ON
)
target_link_libraries(jumbo_test
PRIVATE
nuts::nuts
Eigen3::Eigen
Boost::ut
)

# We build a 'main' object that is linked into each test
add_library(boost_ut_runner OBJECT test_runner.cpp)
target_link_libraries(boost_ut_runner PUBLIC Boost::ut)

function(add_boost_ut_test TEST_NAME)
add_executable(${TEST_NAME} ${TEST_NAME}.cpp)
# boost.UT requires C++20, but our project overall is only C++17
set_property(TARGET ${TEST_NAME} PROPERTY CXX_STANDARD 20)

target_link_libraries(${TEST_NAME}
PRIVATE
boost_ut_runner
Eigen3::Eigen
nuts::nuts
)

# alternative to add_test() that discovers each test in the executable
discover_boost_ut_test(${TEST_NAME})

target_sources(jumbo_test PRIVATE ${TEST_NAME}.cpp)
endfunction()


# 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
)
64 changes: 64 additions & 0 deletions tests/CMake/BoostUTAddTests.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# 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}")
38 changes: 5 additions & 33 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,34 +1,6 @@
if(MSVC)
set(gtest_force_shared_crt on)
endif()
include(CMake/BoostUT.cmake)

FetchContent_Declare(googletest
DOWNLOAD_EXTRACT_TIMESTAMP ON
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG main)
FetchContent_MakeAvailable(googletest)

include(GoogleTest)

# Set up testing framework, then add tests
# define a function to add a gtest‐based nuts test
function(add_nuts_test TEST_NAME TEST_SOURCE)
# create the executable
add_executable(${TEST_NAME} ${TEST_SOURCE})

# link in GoogleTest, Eigen, and your nuts lib
target_link_libraries(${TEST_NAME}
PRIVATE
gtest_main
Eigen3::Eigen
nuts::nuts
)

# register it with CTest
gtest_discover_tests(${TEST_NAME})
endfunction()

add_nuts_test(combine_span_test combine_span_test.cpp)
add_nuts_test(online_moments_test online_moments_test.cpp)
add_nuts_test(dual_average_test dual_average_test.cpp)
add_nuts_test(util_test util_test.cpp)
add_boost_ut_test(combine_span_test)
add_boost_ut_test(dual_average_test)
add_boost_ut_test(online_moments_test)
add_boost_ut_test(util_test)
Loading
Loading