Skip to content

Commit

Permalink
Use Path() objects to store conftest files
Browse files Browse the repository at this point in the history
Using Path().resolve() is better than py.path.realpath because
it resolves to the correct path/drive in case-insensitive file systems (pytest-dev#5792):

>>> from py.path import local
>>> from pathlib import Path
>>>
>>> local('d:\\projects').realpath()
local('d:\\projects')
>>> Path('d:\\projects').resolve()
WindowsPath('D:/projects')

Fix pytest-dev#5819
  • Loading branch information
nicoddemus committed Sep 12, 2019
1 parent 7969131 commit f44cd3f
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 8 deletions.
15 changes: 9 additions & 6 deletions src/_pytest/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,10 +414,7 @@ def _getconftestmodules(self, path):
continue
conftestpath = parent.join("conftest.py")
if conftestpath.isfile():
# Use realpath to avoid loading the same conftest twice
# with build systems that create build directories containing
# symlinks to actual files.
mod = self._importconftest(conftestpath.realpath())
mod = self._importconftest(conftestpath)
clist.append(mod)
self._dirpath2confmods[directory] = clist
return clist
Expand All @@ -432,8 +429,14 @@ def _rget_with_confmod(self, name, path):
raise KeyError(name)

def _importconftest(self, conftestpath):
# Use a resolved Path object as key to avoid loading the same conftest twice
# with build systems that create build directories containing
# symlinks to actual files.
# Using Path().resolve() is better than py.path.realpath because
# it resolves to the correct path/drive in case-insensitive file systems (#5792)
key = Path(str(conftestpath)).resolve()
try:
return self._conftestpath2mod[conftestpath]
return self._conftestpath2mod[key]
except KeyError:
pkgpath = conftestpath.pypkgpath()
if pkgpath is None:
Expand All @@ -450,7 +453,7 @@ def _importconftest(self, conftestpath):
raise ConftestImportFailure(conftestpath, sys.exc_info())

self._conftest_plugins.add(mod)
self._conftestpath2mod[conftestpath] = mod
self._conftestpath2mod[key] = mod
dirpath = conftestpath.dirpath()
if dirpath in self._dirpath2confmods:
for path, mods in self._dirpath2confmods.items():
Expand Down
32 changes: 30 additions & 2 deletions testing/test_conftest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import os
import textwrap
from pathlib import Path

import py

Expand Down Expand Up @@ -163,11 +165,12 @@ def test_setinitial_conftest_subdirs(testdir, name):
subconftest = sub.ensure("conftest.py")
conftest = PytestPluginManager()
conftest_setinitial(conftest, [sub.dirpath()], confcutdir=testdir.tmpdir)
key = Path(str(subconftest)).resolve()
if name not in ("whatever", ".dotdir"):
assert subconftest in conftest._conftestpath2mod
assert key in conftest._conftestpath2mod
assert len(conftest._conftestpath2mod) == 1
else:
assert subconftest not in conftest._conftestpath2mod
assert key not in conftest._conftestpath2mod
assert len(conftest._conftestpath2mod) == 0


Expand Down Expand Up @@ -275,6 +278,31 @@ def fixture():
assert result.ret == ExitCode.OK


@pytest.mark.skipif(
os.path.normcase("x") != os.path.normcase("X"),
reason="only relevant for case insensitive file systems",
)
def test_conftest_badcase(testdir):
"""Check conftest.py loading when directory casing is wrong."""
testdir.tmpdir.mkdir("JenkinsRoot").mkdir("test")
source = {"setup.py": "", "test/__init__.py": "", "test/conftest.py": ""}
testdir.makepyfile(**{"JenkinsRoot/%s" % k: v for k, v in source.items()})

testdir.tmpdir.join("jenkinsroot/test").chdir()
result = testdir.runpytest()
assert result.ret == ExitCode.NO_TESTS_COLLECTED


def test_conftest_uppercase(testdir):
"""Check conftest.py loading when directory casing is wrong."""
source = {"__init__.py": "", "Foo/conftest.py": "", "Foo/__init__.py": ""}
testdir.makepyfile(**source)

testdir.tmpdir.chdir()
result = testdir.runpytest()
assert result.ret == ExitCode.NO_TESTS_COLLECTED


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

0 comments on commit f44cd3f

Please sign in to comment.