Skip to content

Commit

Permalink
Fix Module.name from full path without drive letter
Browse files Browse the repository at this point in the history
  • Loading branch information
nicoddemus committed Aug 15, 2020
1 parent 10f98e1 commit 2213016
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 4 deletions.
1 change: 1 addition & 0 deletions changelog/7628.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix test collection when a full path without a drive letter was passed to pytest on Windows (for example ``\projects\tests\test.py`` instead of ``c:\projects\tests\pytest.py``).
9 changes: 5 additions & 4 deletions src/_pytest/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from _pytest.config.argparsing import Parser
from _pytest.fixtures import FixtureManager
from _pytest.outcomes import exit
from _pytest.pathlib import absolutepath
from _pytest.pathlib import Path
from _pytest.pathlib import visit
from _pytest.reports import CollectReport
Expand Down Expand Up @@ -693,15 +694,15 @@ def _parsearg(self, arg: str) -> Tuple[py.path.local, List[str]]:
strpath, *parts = str(arg).split("::")
if self.config.option.pyargs:
strpath = self._tryconvertpyarg(strpath)
relpath = strpath.replace("/", os.sep)
fspath = self.config.invocation_dir.join(relpath, abs=True)
if not fspath.check():
fspath = Path(str(self.config.invocation_dir), strpath)
fspath = absolutepath(fspath)
if not fspath.exists():
if self.config.option.pyargs:
raise UsageError(
"file or package not found: " + arg + " (missing __init__.py?)"
)
raise UsageError("file not found: " + arg)
return (fspath, parts)
return py.path.local(str(fspath)), parts

def matchnodes(
self, matching: Sequence[Union[nodes.Item, nodes.Collector]], names: List[str],
Expand Down
39 changes: 39 additions & 0 deletions testing/test_collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -1426,3 +1426,42 @@ def test_modules_not_importable_as_side_effect(self, testdir):
"* 1 failed in *",
]
)


def test_module_full_path_without_drive(testdir):
"""Collect and run test using full path except for the drive letter (#7628)
Passing a full path without a drive letter would trigger a bug in py.path.local
where it would keep the full path without the drive letter around, instead of resolving
to the full path, resulting in fixtures node ids not matching against test node ids correctly.
"""
testdir.makepyfile(
**{
"project/conftest.py": """
import pytest
@pytest.fixture
def fix(): return 1
""",
}
)

testdir.makepyfile(
**{
"project/tests/dummy_test.py": """
def test(fix):
assert fix == 1
"""
}
)
fn = testdir.tmpdir.join("project/tests/dummy_test.py")
assert fn.isfile()

drive, path = os.path.splitdrive(str(fn))

result = testdir.runpytest(path, "-v")
result.stdout.fnmatch_lines(
[
os.path.join("project", "tests", "dummy_test.py") + "::test PASSED *",
"* 1 passed in *",
]
)

0 comments on commit 2213016

Please sign in to comment.