diff --git a/cmake/FindPytest.cmake b/cmake/FindPytest.cmake index c40b723..74249d8 100644 --- a/cmake/FindPytest.cmake +++ b/cmake/FindPytest.cmake @@ -166,7 +166,7 @@ if (Pytest_FOUND AND NOT TARGET Pytest::Pytest) set(_WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) endif() - get_filename_component(_WORKING_DIRECTORY "${_WORKING_DIRECTORY}" REALPATH) + get_filename_component(_WORKING_DIRECTORY "${_WORKING_DIRECTORY}" ABSOLUTE) # Override option by environment variable if available. if (DEFINED ENV{BUNDLE_PYTHON_TESTS}) diff --git a/cmake/PytestAddTests.cmake b/cmake/PytestAddTests.cmake index 9b2487f..0e4c79f 100644 --- a/cmake/PytestAddTests.cmake +++ b/cmake/PytestAddTests.cmake @@ -103,9 +103,14 @@ if(CMAKE_SCRIPT_MODE_FILE) set(ENV{PYTEST_CMAKE_DLL_DIRECTORIES} "${DLL_DIRECTORIES}") endif() + # Collect from the resolved path, as Pytest resolves symbolic links in + # the invocation directory but not in 'rootdir'. + # https://github.com/pytest-dev/pytest/issues/12291 + get_filename_component(_collect_directory "${WORKING_DIRECTORY}" REALPATH) + set(_command "${PYTEST_EXECUTABLE}" --collect-only -q - "--rootdir=${WORKING_DIRECTORY}" + "--rootdir=${_collect_directory}" ${DLL_PLUGIN_ARGS} ${DISCOVERY_EXTRA_ARGS} ) @@ -120,7 +125,7 @@ if(CMAKE_SCRIPT_MODE_FILE) OUTPUT_VARIABLE _output_lines ERROR_VARIABLE _output_lines OUTPUT_STRIP_TRAILING_WHITESPACE - WORKING_DIRECTORY ${WORKING_DIRECTORY} + WORKING_DIRECTORY ${_collect_directory} ) # Check for errors during test collection. diff --git a/doc/release/release_notes.rst b/doc/release/release_notes.rst index 65eeece..ed14cb3 100644 --- a/doc/release/release_notes.rst +++ b/doc/release/release_notes.rst @@ -4,6 +4,17 @@ Release Notes ************* +.. release:: Upcoming + + .. change:: fixed + + Updated the :func:`pytest_discover_tests` function to keep symbolic + links in the ``WORKING_DIRECTORY`` value, so that tests run from the + path given instead of the resolved one. Previously, a build tree + configured through a symbolic link could not run its tests once the + link targeted another location. Test collection still uses the + resolved path, as introduced in version 0.5.2. + .. release:: 1.6.1 :date: 2026-09-28 diff --git a/test/05-properties/CMakeLists.txt b/test/05-properties/CMakeLists.txt index 9ffd7c1..2a49327 100644 --- a/test/05-properties/CMakeLists.txt +++ b/test/05-properties/CMakeLists.txt @@ -16,7 +16,7 @@ add_test(NAME TestProperties.Validate.Timeout -D "TEST_PREFIX=TestProperties.Timeout" -D "TEST_PROPERTY=TIMEOUT" -D "EXPECTED_VALUE=120.0" - -P ${CMAKE_CURRENT_LIST_DIR}/check_test_property.cmake + -P ${CMAKE_CURRENT_LIST_DIR}/../utils/check_test_property.cmake ) pytest_discover_tests( @@ -29,7 +29,7 @@ add_test(NAME TestProperties.Validate.Labels -D "TEST_PREFIX=TestProperties.Labels" -D "TEST_PROPERTY=LABELS" -D "EXPECTED_VALUE=[ \"bar\", \"foo\" ]" - -P ${CMAKE_CURRENT_LIST_DIR}/check_test_property.cmake + -P ${CMAKE_CURRENT_LIST_DIR}/../utils/check_test_property.cmake ) pytest_discover_tests( @@ -42,7 +42,7 @@ add_test(NAME TestProperties.Validate.Disabled -D "TEST_PREFIX=TestProperties.Disabled" -D "TEST_PROPERTY=DISABLED" -D "EXPECTED_VALUE=ON" - -P ${CMAKE_CURRENT_LIST_DIR}/check_test_property.cmake + -P ${CMAKE_CURRENT_LIST_DIR}/../utils/check_test_property.cmake ) pytest_discover_tests( @@ -55,5 +55,5 @@ add_test(NAME TestProperties.Validate.SkipReturnCode -D "TEST_PREFIX=TestProperties.SkipReturnCode" -D "TEST_PROPERTY=SKIP_RETURN_CODE" -D "EXPECTED_VALUE=77" - -P ${CMAKE_CURRENT_LIST_DIR}/check_test_property.cmake + -P ${CMAKE_CURRENT_LIST_DIR}/../utils/check_test_property.cmake ) diff --git a/test/07-working-directory/CMakeLists.txt b/test/07-working-directory/CMakeLists.txt index f52b775..aac1465 100644 --- a/test/07-working-directory/CMakeLists.txt +++ b/test/07-working-directory/CMakeLists.txt @@ -16,3 +16,43 @@ pytest_discover_tests( WORKING_DIRECTORY subdir BUNDLE_TESTS ) + +# Link to this directory, using a junction on Windows as it does not require +# elevated privileges. +set(_link "${CMAKE_CURRENT_BINARY_DIR}/link") +if (NOT EXISTS "${_link}") + if (WIN32) + file(TO_NATIVE_PATH "${_link}" _native_link) + file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}" _native_target) + execute_process( + COMMAND cmd /c mklink /J "${_native_link}" "${_native_target}" + OUTPUT_QUIET + COMMAND_ERROR_IS_FATAL ANY + ) + else() + file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}" "${_link}" SYMBOLIC) + endif() +endif() + +# Tests should run from the linked path. Collection must still succeed, without +# loading the conftest file from the parent of the resolved path. +pytest_discover_tests( + TestWorkingDirectory.Link.Simple + WORKING_DIRECTORY "${_link}/subdir" +) + +pytest_discover_tests( + TestWorkingDirectory.Link.Bundled + WORKING_DIRECTORY "${_link}/subdir" + BUNDLE_TESTS +) + +foreach (_variant IN ITEMS Simple Bundled) + add_test(NAME TestWorkingDirectory.Validate.Link.${_variant} + COMMAND ${CMAKE_COMMAND} + -D "TEST_PREFIX=TestWorkingDirectory.Link.${_variant}" + -D "TEST_PROPERTY=WORKING_DIRECTORY" + -D "EXPECTED_VALUE=${_link}/subdir" + -P ${CMAKE_CURRENT_LIST_DIR}/../utils/check_test_property.cmake + ) +endforeach() diff --git a/test/05-properties/check_test_property.cmake b/test/utils/check_test_property.cmake similarity index 100% rename from test/05-properties/check_test_property.cmake rename to test/utils/check_test_property.cmake