Solve fixture ordering when loading plugins from conftest

Conftests are plugins with a location attached to them while other
plugins do not have a location.  When ordering fixturedefs those from
plugins without a location need to be listed first.
This commit is contained in:
Floris Bruynooghe 2013-07-06 17:56:54 +02:00
parent 723e414814
commit e6a063ee47
2 changed files with 41 additions and 7 deletions

View File

@ -1472,8 +1472,7 @@ class FixtureManager:
def pytest_plugin_registered(self, plugin): def pytest_plugin_registered(self, plugin):
if plugin in self._seenplugins: if plugin in self._seenplugins:
return return
#print "plugin_registered", plugin nodeid = None
nodeid = ""
try: try:
p = py.path.local(plugin.__file__) p = py.path.local(plugin.__file__)
except AttributeError: except AttributeError:
@ -1580,8 +1579,8 @@ class FixtureManager:
for fin in reversed(l): for fin in reversed(l):
fin() fin()
def parsefactories(self, node_or_obj, nodeid=None, unittest=False): def parsefactories(self, node_or_obj, nodeid=_dummy, unittest=False):
if nodeid is not None: if nodeid is not _dummy:
holderobj = node_or_obj holderobj = node_or_obj
else: else:
holderobj = node_or_obj.obj holderobj = node_or_obj.obj
@ -1612,7 +1611,15 @@ class FixtureManager:
marker.scope, marker.params, marker.scope, marker.params,
unittest=unittest) unittest=unittest)
faclist = self._arg2fixturedefs.setdefault(name, []) faclist = self._arg2fixturedefs.setdefault(name, [])
faclist.append(fixturedef) if not fixturedef.has_location:
# All Nones are at the front so this inserts the
# current fixturedef after the existing fixturedefs
# from external plugins but before the fixturedefs
# provided in conftests.
i = faclist.count(None)
else:
i = len(faclist) # append
faclist.insert(i, fixturedef)
if marker.autouse: if marker.autouse:
autousenames.append(name) autousenames.append(name)
if autousenames: if autousenames:
@ -1670,7 +1677,8 @@ class FixtureDef:
def __init__(self, fixturemanager, baseid, argname, func, scope, params, def __init__(self, fixturemanager, baseid, argname, func, scope, params,
unittest=False): unittest=False):
self._fixturemanager = fixturemanager self._fixturemanager = fixturemanager
self.baseid = baseid self.baseid = baseid or ''
self.has_location = baseid is not None
self.func = func self.func = func
self.argname = argname self.argname = argname
self.scope = scope self.scope = scope
@ -1721,7 +1729,8 @@ class FixtureDef:
return result return result
def __repr__(self): def __repr__(self):
return "<FixtureDef name=%r scope=%r>" % (self.argname, self.scope) return ("<FixtureDef name=%r scope=%r baseid=%r module=%r>" %
(self.argname, self.scope, self.baseid, self.func.__module__))
def getfuncargnames(function, startindex=None): def getfuncargnames(function, startindex=None):
# XXX merge with main.py's varnames # XXX merge with main.py's varnames

View File

@ -173,6 +173,31 @@ class TestFillFixtures:
result = testdir.runpytest(testfile) result = testdir.runpytest(testfile)
result.stdout.fnmatch_lines(["*1 passed*"]) result.stdout.fnmatch_lines(["*1 passed*"])
def test_extend_fixture_conftest_plugin(request, testdir):
testdir.makepyfile(testplugin="""
import pytest
@pytest.fixture
def foo():
return 7
""")
testdir.syspathinsert()
testdir.makeconftest("""
import pytest
pytest_plugins = 'testplugin'
@pytest.fixture
def foo(foo):
return foo + 7
""")
testdir.makepyfile("""
def test_foo(foo):
assert foo == 14
""")
result = testdir.runpytest('-s')
assert result.ret == 0
def test_funcarg_lookup_error(self, testdir): def test_funcarg_lookup_error(self, testdir):
p = testdir.makepyfile(""" p = testdir.makepyfile("""
def test_lookup_error(unknown): def test_lookup_error(unknown):