Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions changelog/4108.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Resolve symbolic links 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.
2 changes: 1 addition & 1 deletion src/_pytest/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -1175,7 +1175,7 @@ def getfixtureinfo(self, node, func, cls, funcargs=True):
def pytest_plugin_registered(self, plugin):
nodeid = None
try:
p = py.path.local(plugin.__file__)
p = py.path.local(plugin.__file__).realpath()
except AttributeError:
pass
else:
Expand Down
2 changes: 1 addition & 1 deletion src/_pytest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ def _collect(self, arg):
from _pytest.python import Package

names = self._parsearg(arg)
argpath = names.pop(0)
argpath = names.pop(0).realpath()
paths = []

root = self
Expand Down
24 changes: 17 additions & 7 deletions testing/acceptance_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -753,16 +753,26 @@ def join_pythonpath(*dirs):
monkeypatch.syspath_prepend(p)

# module picked up in symlink-ed directory:
# It picks up local/lib/foo/bar (symlink) via sys.path.
result = testdir.runpytest("--pyargs", "-v", "foo.bar")
testdir.chdir()
assert result.ret == 0
result.stdout.fnmatch_lines(
[
"*lib/foo/bar/test_bar.py::test_bar*PASSED*",
"*lib/foo/bar/test_bar.py::test_other*PASSED*",
"*2 passed*",
]
)
if hasattr(py.path.local, "mksymlinkto"):
result.stdout.fnmatch_lines(
[
"lib/foo/bar/test_bar.py::test_bar <- local/lib/foo/bar/test_bar.py PASSED*",
"lib/foo/bar/test_bar.py::test_other <- local/lib/foo/bar/test_bar.py PASSED*",
"*2 passed*",
]
)
else:
result.stdout.fnmatch_lines(
[
"local/lib/foo/bar/test_bar.py::test_bar PASSED*",
"local/lib/foo/bar/test_bar.py::test_other PASSED*",
"*2 passed*",
]
)

def test_cmdline_python_package_not_exists(self, testdir):
result = testdir.runpytest("--pyargs", "tpkgwhatv")
Expand Down
48 changes: 47 additions & 1 deletion testing/test_conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import py
import pytest
from _pytest.config import PytestPluginManager
from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_USAGEERROR
from _pytest.main import EXIT_NOTESTSCOLLECTED, EXIT_OK, EXIT_USAGEERROR


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


@pytest.mark.skipif(
not hasattr(py.path.local, "mksymlinkto"),
reason="symlink not available on this platform",
)
def test_conftest_symlink(testdir):
"""Ensure that conftest.py is used for resolved symlinks."""
realtests = testdir.tmpdir.mkdir("real").mkdir("app").mkdir("tests")
testdir.tmpdir.join("symlinktests").mksymlinkto(realtests)
testdir.makepyfile(
**{
"real/app/tests/test_foo.py": "def test1(fixture): pass",
"real/conftest.py": textwrap.dedent(
"""
import pytest

print("conftest_loaded")

@pytest.fixture
def fixture():
print("fixture_used")
"""
),
}
)
result = testdir.runpytest("-vs", "symlinktests")
result.stdout.fnmatch_lines(
[
"*conftest_loaded*",
"real/app/tests/test_foo.py::test1 fixture_used",
"PASSED",
]
)
assert result.ret == EXIT_OK

realtests.ensure("__init__.py")
result = testdir.runpytest("-vs", "symlinktests/test_foo.py::test1")
result.stdout.fnmatch_lines(
[
"*conftest_loaded*",
"real/app/tests/test_foo.py::test1 fixture_used",
"PASSED",
]
)
assert result.ret == EXIT_OK


def test_no_conftest(testdir):
testdir.makeconftest("assert 0")
result = testdir.runpytest("--noconftest")
Expand Down