Load conftest files in the correct order initially

When the conftest.py files are looked for intially they got loaded
starting from the subdir ending at the parent dir(s).  Later on during
collection any conftest.py files are loaded starting from the parent
dir ending at the subdir.  Due to how extending fixtures works the
latter is correct as otherwise the wrong fixture will be available.
So this changes the initial conftest loading to start at the root and
go towards the subdir.

This does also affect the order of other hooks, hence the order of the
reporting being different in testing/test_terminal.py.
This commit is contained in:
Floris Bruynooghe 2013-04-18 12:24:53 +01:00
parent cf7cae0780
commit c93fbb0e57
4 changed files with 92 additions and 16 deletions

View File

@ -196,27 +196,20 @@ class Conftest(object):
self.getconftestmodules(x)
def getconftestmodules(self, path):
""" return a list of imported conftest modules for the given path. """
try:
clist = self._path2confmods[path]
except KeyError:
if path is None:
raise ValueError("missing default confest.")
dp = path.dirpath()
raise ValueError("missing default conftest.")
clist = []
if dp != path:
cutdir = self._confcutdir
if cutdir and path != cutdir and not path.relto(cutdir):
pass
else:
conftestpath = path.join("conftest.py")
if conftestpath.check(file=1):
clist.append(self.importconftest(conftestpath))
clist[:0] = self.getconftestmodules(dp)
for parent in path.parts():
if self._confcutdir and self._confcutdir.relto(parent):
continue
conftestpath = parent.join("conftest.py")
if conftestpath.check(file=1):
clist.append(self.importconftest(conftestpath))
self._path2confmods[path] = clist
# be defensive: avoid changes from caller side to
# affect us by always returning a copy of the actual list
return clist[:]
return clist
def rget(self, name, path=None):
mod, value = self.rget_with_confmod(name, path)

View File

@ -102,6 +102,77 @@ class TestFillFixtures:
"*2 passed*"
])
def test_extend_fixture_module_class(self, testdir):
testfile = testdir.makepyfile("""
import pytest
@pytest.fixture
def spam():
return 'spam'
class TestSpam:
@pytest.fixture
def spam(self, spam):
return spam * 2
def test_spam(self, spam):
assert spam == 'spamspam'
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines(["*1 passed*"])
result = testdir.runpytest(testfile)
result.stdout.fnmatch_lines(["*1 passed*"])
def test_extend_fixture_conftest_module(self, testdir):
testdir.makeconftest("""
import pytest
@pytest.fixture
def spam():
return 'spam'
""")
testfile = testdir.makepyfile("""
import pytest
@pytest.fixture
def spam(spam):
return spam * 2
def test_spam(spam):
assert spam == 'spamspam'
""")
result = testdir.runpytest()
result.stdout.fnmatch_lines(["*1 passed*"])
result = testdir.runpytest(testfile)
result.stdout.fnmatch_lines(["*1 passed*"])
def test_extend_fixture_conftest_conftest(self, testdir):
testdir.makeconftest("""
import pytest
@pytest.fixture
def spam():
return 'spam'
""")
pkg = testdir.mkpydir("pkg")
pkg.join("conftest.py").write(py.code.Source("""
import pytest
@pytest.fixture
def spam(spam):
return spam * 2
"""))
testfile = pkg.join("test_spam.py")
testfile.write(py.code.Source("""
def test_spam(spam):
assert spam == "spamspam"
"""))
result = testdir.runpytest()
result.stdout.fnmatch_lines(["*1 passed*"])
result = testdir.runpytest(testfile)
result.stdout.fnmatch_lines(["*1 passed*"])
def test_funcarg_lookup_error(self, testdir):
p = testdir.makepyfile("""
def test_lookup_error(unknown):

View File

@ -204,3 +204,15 @@ def test_conftest_confcutdir(testdir):
"""))
result = testdir.runpytest("-h", "--confcutdir=%s" % x, x)
result.stdout.fnmatch_lines(["*--xyz*"])
def test_conftest_import_order(testdir, monkeypatch):
ct1 = testdir.makeconftest("")
sub = testdir.mkdir("sub")
ct2 = sub.join("conftest.py")
ct2.write("")
def impct(p):
print p
return p
conftest = Conftest()
monkeypatch.setattr(conftest, 'importconftest', impct)
assert conftest.getconftestmodules(sub) == [ct1, ct2]

View File

@ -643,9 +643,9 @@ def pytest_report_header(config, startdir):
""")
result = testdir.runpytest("a")
result.stdout.fnmatch_lines([
"*hello: 42*",
"line1",
str(testdir.tmpdir),
"*hello: 42*",
])
@pytest.mark.xfail("not hasattr(os, 'dup')")