From 2213016e40176cdcb1397ad03499ed1881d89ac9 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Thu, 13 Aug 2020 21:37:59 -0300 Subject: [PATCH] Fix Module.name from full path without drive letter Fix #7628 --- changelog/7628.bugfix.rst | 1 + src/_pytest/main.py | 9 +++++---- testing/test_collection.py | 39 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 changelog/7628.bugfix.rst diff --git a/changelog/7628.bugfix.rst b/changelog/7628.bugfix.rst new file mode 100644 index 000000000..9f3480aaa --- /dev/null +++ b/changelog/7628.bugfix.rst @@ -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``). diff --git a/src/_pytest/main.py b/src/_pytest/main.py index c0e1c9d07..e0ca1c0b5 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -31,6 +31,7 @@ from _pytest.config import UsageError 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 @@ -693,15 +694,15 @@ class Session(nodes.FSCollector): 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], diff --git a/testing/test_collection.py b/testing/test_collection.py index 9f22f3ee0..283df082f 100644 --- a/testing/test_collection.py +++ b/testing/test_collection.py @@ -1426,3 +1426,42 @@ class TestImportModeImportlib: "* 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 *", + ] + )