Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/extras
diff options
context:
space:
mode:
authorMartin Hořeňovský2025-01-03 10:30:47 +0100
committerMartin Hořeňovský2025-01-05 20:02:00 +0100
commit7d7b2f89f24cbd277f6eb6912705e5e13c68a3c7 (patch)
treede5bfb1374a86468196ac71b48ca74651782d0ab /extras
parentb0d0aa43e6785f01e2dc4708c23fd8903de26c5c (diff)
downloadcatch3-7d7b2f89f24cbd277f6eb6912705e5e13c68a3c7.tar.gz
Support adding test tags as CTest labels in catch_discover_tests
We also bump the minimum CMake version to 3.20 as per #2943
Diffstat (limited to 'extras')
-rw-r--r--extras/Catch.cmake32
-rw-r--r--extras/CatchAddTests.cmake86
2 files changed, 76 insertions, 42 deletions
diff --git a/extras/Catch.cmake b/extras/Catch.cmake
index cef73def..3d93fe20 100644
--- a/extras/Catch.cmake
+++ b/extras/Catch.cmake
@@ -39,6 +39,7 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
[OUTPUT_SUFFIX suffix]
[DISCOVERY_MODE <POST_BUILD|PRE_TEST>]
[SKIP_IS_FAILURE]
+ [ADD_TAGS_AS_LABELS]
)
``catch_discover_tests`` sets up a post-build command on the test executable
@@ -148,6 +149,9 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``.
``SKIP_IS_FAILURE``
Disables skipped test detection.
+ ``ADD_TAGS_AS_LABELS``
+ Adds all test tags as CTest labels.
+
#]=======================================================================]
#------------------------------------------------------------------------------
@@ -155,12 +159,16 @@ function(catch_discover_tests TARGET)
cmake_parse_arguments(
""
- "SKIP_IS_FAILURE"
+ "SKIP_IS_FAILURE;ADD_TAGS_AS_LABELS"
"TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;REPORTER;OUTPUT_DIR;OUTPUT_PREFIX;OUTPUT_SUFFIX;DISCOVERY_MODE"
"TEST_SPEC;EXTRA_ARGS;PROPERTIES;DL_PATHS;DL_FRAMEWORK_PATHS"
${ARGN}
)
+ if (${CMAKE_VERSION} VERSION_LESS "3.19")
+ message(FATAL_ERROR "This script requires JSON support from CMake version 3.19 or greater.")
+ endif()
+
if(NOT _WORKING_DIRECTORY)
set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
endif()
@@ -222,6 +230,7 @@ function(catch_discover_tests TARGET)
-D "TEST_DL_PATHS=${_DL_PATHS}"
-D "TEST_DL_FRAMEWORK_PATHS=${_DL_FRAMEWORK_PATHS}"
-D "CTEST_FILE=${ctest_tests_file}"
+ -D "ADD_TAGS_AS_LABELS=${_ADD_TAGS_AS_LABELS}"
-P "${_CATCH_DISCOVER_TESTS_SCRIPT}"
VERBATIM
)
@@ -267,6 +276,7 @@ function(catch_discover_tests TARGET)
" CTEST_FILE" " [==[" "${ctest_tests_file}" "]==]" "\n"
" TEST_DL_PATHS" " [==[" "${_DL_PATHS}" "]==]" "\n"
" TEST_DL_FRAMEWORK_PATHS" " [==[" "${_DL_FRAMEWORK_PATHS}" "]==]" "\n"
+ " ADD_TAGS_AS_LABELS" " [==[" "${_ADD_TAGS_AS_LABELS}" "]==]" "\n"
" )" "\n"
" endif()" "\n"
" include(\"${ctest_tests_file}\")" "\n"
@@ -293,22 +303,10 @@ function(catch_discover_tests TARGET)
endif()
endif()
- if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0")
- # Add discovered tests to directory TEST_INCLUDE_FILES
- set_property(DIRECTORY
- APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}"
- )
- else()
- # Add discovered tests as directory TEST_INCLUDE_FILE if possible
- get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET)
- if (NOT ${test_include_file_set})
- set_property(DIRECTORY
- PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}"
- )
- else()
- message(FATAL_ERROR "Cannot set more than one TEST_INCLUDE_FILE")
- endif()
- endif()
+ # Add discovered tests to directory TEST_INCLUDE_FILES
+ set_property(DIRECTORY
+ APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}"
+ )
endfunction()
diff --git a/extras/CatchAddTests.cmake b/extras/CatchAddTests.cmake
index 399a839d..ceaf8652 100644
--- a/extras/CatchAddTests.cmake
+++ b/extras/CatchAddTests.cmake
@@ -22,10 +22,11 @@ function(catch_discover_tests_impl)
""
""
"TEST_EXECUTABLE;TEST_WORKING_DIR;TEST_OUTPUT_DIR;TEST_OUTPUT_PREFIX;TEST_OUTPUT_SUFFIX;TEST_PREFIX;TEST_REPORTER;TEST_SPEC;TEST_SUFFIX;TEST_LIST;CTEST_FILE"
- "TEST_EXTRA_ARGS;TEST_PROPERTIES;TEST_EXECUTOR;TEST_DL_PATHS;TEST_DL_FRAMEWORK_PATHS"
+ "TEST_EXTRA_ARGS;TEST_PROPERTIES;TEST_EXECUTOR;TEST_DL_PATHS;TEST_DL_FRAMEWORK_PATHS;ADD_TAGS_AS_LABELS"
${ARGN}
)
+ set(add_tags "${_ADD_TAGS_AS_LABELS}")
set(prefix "${_TEST_PREFIX}")
set(suffix "${_TEST_SUFFIX}")
set(spec ${_TEST_SPEC})
@@ -72,25 +73,19 @@ function(catch_discover_tests_impl)
endif()
execute_process(
- COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" ${spec} --list-tests --verbosity quiet
- OUTPUT_VARIABLE output
+ COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" ${spec} --list-tests --reporter json
+ OUTPUT_VARIABLE listing_output
RESULT_VARIABLE result
WORKING_DIRECTORY "${_TEST_WORKING_DIR}"
)
if(NOT ${result} EQUAL 0)
message(FATAL_ERROR
- "Error running test executable '${_TEST_EXECUTABLE}':\n"
+ "Error listing tests from executable '${_TEST_EXECUTABLE}':\n"
" Result: ${result}\n"
- " Output: ${output}\n"
+ " Output: ${listing_output}\n"
)
endif()
- # Make sure to escape ; (semicolons) in test names first, because
- # that'd break the foreach loop for "Parse output" later and create
- # wrongly splitted and thus failing test cases (false positives)
- string(REPLACE ";" "\;" output "${output}")
- string(REPLACE "\n" ";" output "${output}")
-
# Prepare reporter
if(reporter)
set(reporter_arg "--reporter ${reporter}")
@@ -110,7 +105,7 @@ function(catch_discover_tests_impl)
)
elseif(NOT ${reporter_check_result} EQUAL 0)
message(FATAL_ERROR
- "Error running test executable '${_TEST_EXECUTABLE}':\n"
+ "Error checking for reporter in test executable '${_TEST_EXECUTABLE}':\n"
" Result: ${reporter_check_result}\n"
" Output: ${reporter_check_output}\n"
)
@@ -139,46 +134,86 @@ function(catch_discover_tests_impl)
endforeach()
endif()
- # Parse output
- foreach(line ${output})
- set(test "${line}")
+ # Parse JSON output for list of tests/class names/tags
+ string(JSON version GET "${listing_output}" "version")
+ if (NOT version STREQUAL "1")
+ message(FATAL_ERROR "Unsupported catch output version: '${version}'")
+ endif()
+
+ # Speed-up reparsing by cutting away unneeded parts of JSON.
+ string(JSON test_listing GET "${listing_output}" "listings" "tests")
+ string(JSON num_tests LENGTH "${test_listing}")
+ # CMake's foreach-RANGE is inclusive, so we have to subtract 1
+ math(EXPR num_tests "${num_tests} - 1")
+
+ foreach(idx RANGE ${num_tests})
+ string(JSON single_test GET ${test_listing} ${idx})
+ string(JSON test_tags GET "${single_test}" "tags")
+ string(JSON plain_name GET "${single_test}" "name")
+
# Escape characters in test case names that would be parsed by Catch2
# Note that the \ escaping must happen FIRST! Do not change the order.
- set(test_name "${test}")
- foreach(char \\ , [ ])
- string(REPLACE ${char} "\\${char}" test_name "${test_name}")
+ set(escaped_name "${plain_name}")
+ foreach(char \\ , [ ] ;)
+ string(REPLACE ${char} "\\${char}" escaped_name "${escaped_name}")
endforeach(char)
# ...add output dir
if(output_dir)
- string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean "${test_name}")
- set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}")
+ string(REGEX REPLACE "[^A-Za-z0-9_]" "_" escaped_name_clean "${escaped_name}")
+ set(output_dir_arg "--out ${output_dir}/${output_prefix}${escaped_name_clean}${output_suffix}")
endif()
# ...and add to script
add_command(add_test
- "${prefix}${test}${suffix}"
+ "${prefix}${plain_name}${suffix}"
${_TEST_EXECUTOR}
"${_TEST_EXECUTABLE}"
- "${test_name}"
+ "${escaped_name}"
${extra_args}
"${reporter_arg}"
"${output_dir_arg}"
)
add_command(set_tests_properties
- "${prefix}${test}${suffix}"
+ "${prefix}${plain_name}${suffix}"
PROPERTIES
WORKING_DIRECTORY "${_TEST_WORKING_DIR}"
${properties}
)
+ if (add_tags)
+ string(JSON num_tags LENGTH "${test_tags}")
+ math(EXPR num_tags "${num_tags} - 1")
+ set(tag_list "")
+ if (num_tags GREATER_EQUAL "0")
+ foreach(tag_idx RANGE ${num_tags})
+ string(JSON a_tag GET "${test_tags}" "${tag_idx}")
+ # Catch2's tags can contain semicolons, which are list element separators
+ # in CMake, so we have to escape them. Ideally we could use the [=[...]=]
+ # syntax for this, but CTest currently keeps the square quotes in the label
+ # name. So we add 2 backslashes to escape it instead.
+ # **IMPORTANT**: The number of backslashes depends on how many layers
+ # of CMake the tag goes. If this script is changed, the
+ # number of backslashes to escape may change as well.
+ string(REPLACE ";" "\\;" a_tag "${a_tag}")
+ list(APPEND tag_list "${a_tag}")
+ endforeach()
+
+ add_command(set_tests_properties
+ "${prefix}${plain_name}${suffix}"
+ PROPERTIES
+ LABELS "${tag_list}"
+ )
+ endif()
+ endif(add_tags)
+
if(environment_modifications)
add_command(set_tests_properties
- "${prefix}${test}${suffix}"
+ "${prefix}${plain_name}${suffix}"
PROPERTIES
ENVIRONMENT_MODIFICATION "${environment_modifications}")
endif()
- list(APPEND tests "${prefix}${test}${suffix}")
+ list(APPEND tests "${prefix}${plain_name}${suffix}")
endforeach()
# Create a list of all discovered tests, which users may use to e.g. set
@@ -207,5 +242,6 @@ if(CMAKE_SCRIPT_MODE_FILE)
TEST_DL_PATHS ${TEST_DL_PATHS}
TEST_DL_FRAMEWORK_PATHS ${TEST_DL_FRAMEWORK_PATHS}
CTEST_FILE ${CTEST_FILE}
+ ADD_TAGS_AS_LABELS ${ADD_TAGS_AS_LABELS}
)
endif()