@@ -3,54 +3,62 @@ cmake_minimum_required(VERSION 3.20...3.30)
33
44if (CMAKE_SCRIPT_MODE_FILE )
55
6- # Set Cmake test file to execute each test.
6+ # Initialize content for the CMake test file .
77 set (_content "" )
88
9+ # Convert library and Python paths to native format.
910 cmake_path (CONVERT "${LIBRARY_PATH} " TO_NATIVE_PATH_LIST LIBRARY_PATH )
1011 cmake_path (CONVERT "${PYTHON_PATH} " TO_NATIVE_PATH_LIST PYTHON_PATH )
1112
1213 # Serialize path values separated by semicolons (required on Windows).
13- macro (encode_value VARIABLE_NAME )
14- string (REPLACE [[ \]] [[ \\]] ${VARIABLE_NAME} "${${VARIABLE_NAME} }" )
15- string (REPLACE [[ ;]] [[ \\;]] ${VARIABLE_NAME} "${${VARIABLE_NAME} }" )
16- endmacro ()
17-
18- encode_value (LIBRARY_PATH )
19- encode_value (PYTHON_PATH )
20-
21- if (BUNDLE_TESTS)
14+ string (REPLACE [[ ;]] [[ \\;]] LIBRARY_PATH "${LIBRARY_PATH} " )
15+ string (REPLACE [[ ;]] [[ \\;]] PYTHON_PATH "${PYTHON_PATH} " )
16+
17+ # Set up the encoded environment with required paths.
18+ set (ENCODED_ENVIRONMENT
19+ "${LIBRARY_ENV_NAME} =${LIBRARY_PATH} "
20+ "PYTHONPATH=${PYTHON_PATH} "
21+ )
22+
23+ # Serialize additional environment variables if any are provided.
24+ foreach (env ${ENVIRONMENT} )
25+ string (REPLACE [[ ;]] [[ \\;]] env "${env} " )
26+ list (APPEND ENCODED_ENVIRONMENT "${env} " )
27+ endforeach ()
28+
29+ # Macro to create individual tests with optional test properties.
30+ macro (create_test NAME IDENTIFIER )
2231 string (APPEND _content
23- "add_test(\n "
24- " \" ${TEST_GROUP_NAME} \"\n "
25- " \" ${PYTEST_EXECUTABLE} \" \" ${WORKING_DIRECTORY} \"\n "
26- ")\n "
27- "set_tests_properties(\n "
28- " \" ${TEST_GROUP_NAME} \" PROPERTIES\n "
29- " ENVIRONMENT \" ${LIBRARY_ENV_NAME} =${LIBRARY_PATH} \"\n "
30- ")\n "
31- "set_tests_properties(\n "
32- " \" ${TEST_GROUP_NAME} \"\n "
33- " APPEND PROPERTIES\n "
34- " ENVIRONMENT \" PYTHONPATH=${PYTHON_PATH} \"\n "
35- ")\n "
32+ "add_test(\" ${NAME} \" \" ${PYTEST_EXECUTABLE} \" \" ${IDENTIFIER} \" )\n "
3633 )
3734
38- foreach (env ${ENVIRONMENT} )
39- string (APPEND _content
40- "set_tests_properties(\n "
41- " \" ${TEST_GROUP_NAME} \"\n "
42- " APPEND PROPERTIES\n "
43- " ENVIRONMENT ${env} \n "
44- ")\n "
45- )
35+ # Prepare the properties for the test, including the environment settings.
36+ set (args "PROPERTIES ENVIRONMENT [==[${ENCODED_ENVIRONMENT} ]==]" )
37+
38+ # Append any additional properties, escaping complex characters if necessary.
39+ foreach (property ${TEST_PROPERTIES} )
40+ if (property MATCHES "[^-./:a-zA-Z0-9_]" )
41+ string (APPEND args " [==[${property} ]==]" )
42+ else ()
43+ string (APPEND args " ${property} " )
44+ endif ()
4645 endforeach ()
4746
47+ # Append the test properties to the content.
48+ string (APPEND _content "set_tests_properties(\" ${NAME} \" ${args} )\n " )
49+ endmacro ()
50+
51+ # If tests are bundled together, create a single test group.
52+ if (BUNDLE_TESTS)
53+ create_test ("${TEST_GROUP_NAME} " "${WORKING_DIRECTORY} " )
54+
4855 else ()
49- # Set environment for collecting tests.
56+ # Set environment variables for collecting tests.
5057 set (ENV{${LIBRARY_ENV_NAME} } "${LIBRARY_PATH} " )
5158 set (ENV{PYTHONPATH} "${PYTHON_PATH} " )
5259 set (ENV{PYTHONWARNINGS} "ignore" )
5360
61+ # Collect tests.
5462 execute_process (
5563 COMMAND "${PYTEST_EXECUTABLE} "
5664 --collect-only -q
@@ -61,91 +69,80 @@ if(CMAKE_SCRIPT_MODE_FILE)
6169 WORKING_DIRECTORY ${WORKING_DIRECTORY}
6270 )
6371
72+ # Check for errors during test collection.
6473 string (REGEX MATCH "=+ ERRORS =+(.*)" _error "${_output_lines} " )
6574
6675 if (_error)
6776 message (${_error} )
6877 message (FATAL_ERROR "An error occurred during the collection of Python tests." )
6978 endif ()
7079
71- # Convert output into list.
80+ # Convert the collected output into a list of lines .
7281 string (REPLACE [[ ;]] [[ \;]] _output_lines "${_output_lines} " )
7382 string (REPLACE "\n " ";" _output_lines "${_output_lines} " )
7483
84+ # Regex pattern to identify pytest test identifiers.
7585 set (test_pattern "([^:]+)\. py(::([^:]+))?::([^:]+)" )
7686
77- foreach (line ${_output_lines} )
87+ # Iterate through each line to identify and process tests.
88+ foreach (line ${_output_lines} )
7889 string (REGEX MATCHALL ${test_pattern} matching "${line} " )
7990
80- # Ignore lines not identified as a test .
91+ # Skip lines that are not identified as tests .
8192 if (NOT matching)
8293 continue ()
8394 endif ()
8495
96+ # Extract file, class, and function names from the test pattern.
8597 set (_file ${CMAKE_MATCH_1} )
8698 set (_class ${CMAKE_MATCH_3} )
8799 set (_func ${CMAKE_MATCH_4} )
88100
101+ # Optionally trim parts of the class or function name.
89102 if (TRIM_FROM_NAME)
90103 string (REGEX REPLACE "${TRIM_FROM_NAME} " "" _class "${_class} " )
91104 string (REGEX REPLACE "${TRIM_FROM_NAME} " "" _func "${_func} " )
92105 endif ()
93106
107+ # Form the test name using class and function.
94108 if (_class)
95109 set (test_name "${_class} .${_func} " )
96110 else ()
97111 set (test_name "${_func} " )
98112 endif ()
99113
114+ # Optionally strip parameter brackets from the test name.
100115 if (STRIP_PARAM_BRACKETS)
101116 string (REGEX REPLACE "\\ [(.+)\\ ]$" ".\\ 1" test_name "${test_name} " )
102117 endif ()
103118
119+ # Optionally include the file path in the test name.
104120 if (INCLUDE_FILE_PATH)
105121 cmake_path (CONVERT "${_file} " TO_CMAKE_PATH_LIST _file )
106122 string (REGEX REPLACE "/" "." _file "${_file} " )
107123 set (test_name "${_file} .${test_name} " )
108124 endif ()
109125
126+ # Optionally trim parts of the full test name.
110127 if (TRIM_FROM_FULL_NAME)
111128 string (REGEX REPLACE "${TRIM_FROM_FULL_NAME} " "" test_name "${test_name} " )
112129 endif ()
113130
131+ # Prefix the test name with the test group name.
114132 set (test_name "${TEST_GROUP_NAME} .${test_name} " )
115133 set (test_case "${WORKING_DIRECTORY} /${line} " )
116134
117- string (APPEND _content
118- "add_test(\n "
119- " \" ${test_name} \"\n "
120- " \" ${PYTEST_EXECUTABLE} \" \" ${test_case} \"\n "
121- ")\n "
122- "set_tests_properties(\n "
123- " \" ${test_name} \" PROPERTIES\n "
124- " ENVIRONMENT \" ${LIBRARY_ENV_NAME} =${LIBRARY_PATH} \"\n "
125- ")\n "
126- "set_tests_properties(\n "
127- " \" ${test_name} \"\n "
128- " APPEND PROPERTIES\n "
129- " ENVIRONMENT \" PYTHONPATH=${PYTHON_PATH} \"\n "
130- ")\n "
131- )
132-
133- foreach (env ${ENVIRONMENT} )
134- string (APPEND _content
135- "set_tests_properties(\n "
136- " \" ${test_name} \"\n "
137- " APPEND PROPERTIES\n "
138- " ENVIRONMENT ${env} \n "
139- ")\n "
140- )
141- endforeach ()
142-
135+ # Create the test for CTest.
136+ create_test ("${test_name} " "${test_case} " )
143137 endforeach ()
144138
139+ # Warn if no tests were discovered.
145140 if (NOT _content)
146141 message (WARNING "No Python tests have been discovered." )
147142 endif ()
148143 endif ()
149144
145+ # Write the generated test content to the specified CTest file.
150146 file (WRITE ${CTEST_FILE} ${_content} )
147+
151148endif ()
0 commit comments