pytest icon indicating copy to clipboard operation
pytest copied to clipboard

Incorrect confcutdir inferred when rootdir is under a symlink directory

Open buddly27 opened this issue 1 year ago • 0 comments

When a test directory is nested within a symlinked directory, it can lead to errors when the 'rootdir' or the invocation directory targets the unresolved path, especially when the symlink targets a different storage structure.

> ln -s /tmp/test /path/to/test/path
> cd /tmp/test
> pytest --rootdir=/tmp/test .

==================================== ERRORS ====================================
________________________ ERROR collecting test session _________________________
...
/usr/lib/python3.10/path lib.py:1097: PermissionError
=========================== Short test summary info ============================
ERROR ../../path/to/test/path::dir - PermissionError: [Errno 13] Permission denied: '/..../__init__.py'
=============================== 1 error in 0.14s ===============================

> pytest --rootdir=. /tmp/test 
# Same error ...

This issue does not occur when both the 'rootdir' and invocation directory use the same path (resolved or unresolved).

The invocation directory defaults to Path.cwd() which resolves the symlink, and relative entries seem to be normalized via pathlib.absolutepath (using os.path.abspath under the hood), which also returns a resolved path in some situations:

> pwd
/tmp/test

> python -c "import pathlib; print(pathlib.Path.cwd())"
/path/to/test/path

> python -c "import os; print(os.path.abspath('.'))"
/path/to/test/path

By default, the 'confcutdir' value is inferred from the 'rootdir' value, which is inferred from the invocation path, so it doesn't seem to be a problem. But in cases where the invocation path is defined to use the resolved path, while the 'rootdir' value is defined to use the unresolved path (or vice versa), the Session collector may encounter difficulties determining where to stop when searching for configs: https://github.com/pytest-dev/pytest/blob/84e59af8c829de659efb339d5a9c7cec98eee719/src/_pytest/main.py#L861-L869

This issue could be solved by automatically resolving the value used for 'rootdir', but I'm not sure if there are any drawbacks to this approach (aside from performance).

I ran these tests on MacOS and Linux using Pytest 8.2.0 and Python 3.10.

I also setup a small repository to reproduce the errors via a Github workflow for more details: https://github.com/buddly27/pytest-issue/actions/runs/8973032152/job/24642315352

buddly27 avatar May 06 '24 20:05 buddly27