diff --git a/changelog/9767.bugfix.rst b/changelog/9767.bugfix.rst new file mode 100644 index 00000000000..7de316980b8 --- /dev/null +++ b/changelog/9767.bugfix.rst @@ -0,0 +1 @@ +Fixed a regression in pytest 7.1.0 where some conftest.py files outside of the source tree (e.g. in the `site-packages` directory) were not picked up. diff --git a/extra/setup-py.test/setup.py b/extra/setup-py.test/setup.py index d0560ce1f5f..97883852e2e 100644 --- a/extra/setup-py.test/setup.py +++ b/extra/setup-py.test/setup.py @@ -1,4 +1,5 @@ import sys + from distutils.core import setup if __name__ == "__main__": diff --git a/src/_pytest/config/__init__.py b/src/_pytest/config/__init__.py index f4818c861cf..91ad3f094ff 100644 --- a/src/_pytest/config/__init__.py +++ b/src/_pytest/config/__init__.py @@ -538,11 +538,7 @@ def _is_in_confcutdir(self, path: Path) -> bool: """ if self._confcutdir is None: return True - try: - path.relative_to(self._confcutdir) - except ValueError: - return False - return True + return path not in self._confcutdir.parents def _try_load_conftest( self, anchor: Path, importmode: Union[str, ImportMode], rootpath: Path diff --git a/testing/test_conftest.py b/testing/test_conftest.py index 4cbc2d14c36..68048204581 100644 --- a/testing/test_conftest.py +++ b/testing/test_conftest.py @@ -252,6 +252,34 @@ def pytest_addoption(parser): result.stdout.no_fnmatch_line("*warning: could not load initial*") +def test_installed_conftest_is_picked_up(pytester: Pytester, tmp_path: Path) -> None: + """When using `--pyargs` to run tests in an installed packages (located e.g. + in a site-packages in the PYTHONPATH), conftest files in there are picked + up. + + Regression test for #9767. + """ + # pytester dir - the source tree. + # tmp_path - the simulated site-packages dir (not in source tree). + + pytester.syspathinsert(tmp_path) + pytester.makepyprojecttoml("[tool.pytest.ini_options]") + tmp_path.joinpath("foo").mkdir() + tmp_path.joinpath("foo", "__init__.py").touch() + tmp_path.joinpath("foo", "conftest.py").write_text( + textwrap.dedent( + """\ + import pytest + @pytest.fixture + def fix(): return None + """ + ) + ) + tmp_path.joinpath("foo", "test_it.py").write_text("def test_it(fix): pass") + result = pytester.runpytest("--pyargs", "foo") + assert result.ret == 0 + + def test_conftest_symlink(pytester: Pytester) -> None: """`conftest.py` discovery follows normal path resolution and does not resolve symlinks.""" # Structure: