Skip to content

Commit 17aaa3b

Browse files
committed
Resolve symlinks for args
This fixes running `pytest tests/test_foo.py::test_bar`, where `tests` is a symlink to `project/app/tests`: previously `project/app/conftest.py` would be ignored for fixtures then.
1 parent 4c9015c commit 17aaa3b

File tree

5 files changed

+53
-5
lines changed

5 files changed

+53
-5
lines changed

changelog/4108.bugfix.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Resolve symbolic links for args.
2+
3+
This fixes running `pytest tests/test_foo.py::test_bar`, where `tests`
4+
is a symlink to `project/app/tests`:
5+
previously `project/app/conftest.py` would be ignored for fixtures then.

src/_pytest/fixtures.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1172,7 +1172,7 @@ def getfixtureinfo(self, node, func, cls, funcargs=True):
11721172
def pytest_plugin_registered(self, plugin):
11731173
nodeid = None
11741174
try:
1175-
p = py.path.local(plugin.__file__)
1175+
p = py.path.local(plugin.__file__).realpath()
11761176
except AttributeError:
11771177
pass
11781178
else:

src/_pytest/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ def _collect(self, arg):
487487
from _pytest.python import Package
488488

489489
names = self._parsearg(arg)
490-
argpath = names.pop(0)
490+
argpath = names.pop(0).realpath()
491491
paths = []
492492

493493
root = self

testing/acceptance_test.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -733,13 +733,14 @@ def join_pythonpath(*dirs):
733733
monkeypatch.syspath_prepend(p)
734734

735735
# module picked up in symlink-ed directory:
736+
# It picks up local/lib/foo/bar (symlink) via sys.path.
736737
result = testdir.runpytest("--pyargs", "-v", "foo.bar")
737738
testdir.chdir()
738739
assert result.ret == 0
739740
result.stdout.fnmatch_lines(
740741
[
741-
"*lib/foo/bar/test_bar.py::test_bar*PASSED*",
742-
"*lib/foo/bar/test_bar.py::test_other*PASSED*",
742+
"lib/foo/bar/test_bar.py::test_bar <- local/lib/foo/bar/test_bar.py PASSED*",
743+
"lib/foo/bar/test_bar.py::test_other <- local/lib/foo/bar/test_bar.py PASSED*",
743744
"*2 passed*",
744745
]
745746
)

testing/test_conftest.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import py
55
import pytest
66
from _pytest.config import PytestPluginManager
7-
from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR
7+
from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_OK, EXIT_USAGEERROR
88

99

1010
@pytest.fixture(scope="module", params=["global", "inpackage"])
@@ -186,6 +186,48 @@ def pytest_addoption(parser):
186186
assert "warning: could not load initial" not in result.stdout.str()
187187

188188

189+
@pytest.mark.skipif(
190+
not hasattr(py.path.local, "mksymlinkto"),
191+
reason="symlink not available on this platform",
192+
)
193+
def test_conftest_symlink(testdir):
194+
"""Ensure that conftest.py is used for resolved symlinks."""
195+
realtests = testdir.tmpdir.mkdir("real").mkdir("app").mkdir("tests")
196+
testdir.tmpdir.join("symlinktests").mksymlinkto(realtests)
197+
testdir.makepyfile(
198+
**{
199+
"real/app/tests/test_foo.py": "def test1(fixture): pass",
200+
"real/conftest.py": textwrap.dedent(
201+
"""
202+
import pytest
203+
204+
print("conftest_loaded")
205+
206+
@pytest.fixture
207+
def fixture():
208+
print("fixture_used")
209+
"""
210+
),
211+
}
212+
)
213+
result = testdir.runpytest("-vs", "symlinktests")
214+
result.stdout.fnmatch_lines([
215+
"*conftest_loaded*",
216+
"real/app/tests/test_foo.py::test1 fixture_used",
217+
"PASSED",
218+
])
219+
assert result.ret == EXIT_OK
220+
221+
realtests.ensure("__init__.py")
222+
result = testdir.runpytest("-vs", "symlinktests/test_foo.py::test1")
223+
result.stdout.fnmatch_lines([
224+
"*conftest_loaded*",
225+
"real/app/tests/test_foo.py::test1 fixture_used",
226+
"PASSED",
227+
])
228+
assert result.ret == EXIT_OK
229+
230+
189231
def test_no_conftest(testdir):
190232
testdir.makeconftest("assert 0")
191233
result = testdir.runpytest("--noconftest")

0 commit comments

Comments
 (0)