internally unify setup and fixture code, making setup a shortcut to fixture(autoactive=True)

This commit is contained in:
holger krekel 2012-10-05 10:21:35 +02:00
parent 9251e747af
commit 8282efbb40
4 changed files with 128 additions and 175 deletions

View File

@ -41,7 +41,7 @@ def pytest_make_collect_report(collector):
def call_optional(obj, name): def call_optional(obj, name):
method = getattr(obj, name, None) method = getattr(obj, name, None)
if method is not None and not hasattr(method, "_pytestsetup"): if method is not None and not hasattr(method, "_pytestfixturefunction"):
# If there's any problems allow the exception to raise rather than # If there's any problems allow the exception to raise rather than
# silently ignoring them # silently ignoring them
method() method()

View File

@ -11,22 +11,18 @@ import _pytest
cutdir = py.path.local(_pytest.__file__).dirpath() cutdir = py.path.local(_pytest.__file__).dirpath()
class FixtureFunctionMarker: class FixtureFunctionMarker:
def __init__(self, scope, params): def __init__(self, scope, params, autoactive=False):
self.scope = scope self.scope = scope
self.params = params self.params = params
self.autoactive = autoactive
def __call__(self, function): def __call__(self, function):
function._pytestfixturefunction = self function._pytestfixturefunction = self
return function return function
class SetupMarker:
def __init__(self, scope):
self.scope = scope
def __call__(self, function):
function._pytestsetup = self
return function
# XXX a test fails when scope="function" how it should be, investigate # XXX a test fails when scope="function" how it should be, investigate
def fixture(scope=None, params=None): def fixture(scope=None, params=None, autoactive=False):
""" return a decorator to mark a fixture factory function. """ return a decorator to mark a fixture factory function.
The name of the fixture function can be referenced in a test context The name of the fixture function can be referenced in a test context
@ -42,8 +38,11 @@ def fixture(scope=None, params=None):
invocations of the fixture functions and their dependent invocations of the fixture functions and their dependent
tests. tests.
""" """
return FixtureFunctionMarker(scope, params) return FixtureFunctionMarker(scope, params, autoactive=autoactive)
defaultfuncargprefixmarker = fixture()
# XXX remove in favour of fixture(autoactive=True)
def setup(scope="function"): def setup(scope="function"):
""" return a decorator to mark a function as providing a fixture for """ return a decorator to mark a function as providing a fixture for
a testcontext. A fixture function is executed for each scope and may a testcontext. A fixture function is executed for each scope and may
@ -57,7 +56,7 @@ def setup(scope="function"):
of "function", "class", "module", "session". of "function", "class", "module", "session".
Defaults to "function". Defaults to "function".
""" """
return SetupMarker(scope) return FixtureFunctionMarker(scope, params=None, autoactive=True)
def cached_property(f): def cached_property(f):
"""returns a cached property that is calculated by function f. """returns a cached property that is calculated by function f.
@ -163,7 +162,10 @@ def pytest_pyfunc_call(__multicall__, pyfuncitem):
testfunction(*pyfuncitem._args) testfunction(*pyfuncitem._args)
else: else:
funcargs = pyfuncitem.funcargs funcargs = pyfuncitem.funcargs
testfunction(**funcargs) testargs = {}
for arg in getfuncargnames(testfunction):
testargs[arg] = funcargs[arg]
testfunction(**testargs)
def pytest_collect_file(path, parent): def pytest_collect_file(path, parent):
ext = path.ext ext = path.ext
@ -666,7 +668,6 @@ class Metafunc:
for i, valset in enumerate(argvalues): for i, valset in enumerate(argvalues):
assert len(valset) == len(argnames) assert len(valset) == len(argnames)
newcallspec = callspec.copy(self) newcallspec = callspec.copy(self)
#print ("setmulti %r id %r" % (argnames, ids[i]))
newcallspec.setmulti(valtype, argnames, valset, ids[i], newcallspec.setmulti(valtype, argnames, valset, ids[i],
scopenum) scopenum)
newcalls.append(newcallspec) newcalls.append(newcallspec)
@ -879,14 +880,19 @@ class Function(FunctionMixin, pytest.Item):
#req._discoverfactories() #req._discoverfactories()
if callobj is not _dummy: if callobj is not _dummy:
self.obj = callobj self.obj = callobj
startindex = int(self.cls is not None) self.funcargnames = self._getfixturenames()
self.funcargnames = getfuncargnames(self.obj, startindex=startindex)
for name, val in (py.builtin._getfuncdict(self.obj) or {}).items(): for name, val in (py.builtin._getfuncdict(self.obj) or {}).items():
setattr(self.markers, name, val) setattr(self.markers, name, val)
if keywords: if keywords:
for name, val in keywords.items(): for name, val in keywords.items():
setattr(self.markers, name, val) setattr(self.markers, name, val)
def _getfixturenames(self):
startindex = int(self.cls is not None)
return (self.session.funcargmanager._autofixtures +
getfuncargnames(self.obj, startindex=startindex))
@property @property
def function(self): def function(self):
"underlying python 'function' object" "underlying python 'function' object"
@ -913,8 +919,8 @@ class Function(FunctionMixin, pytest.Item):
def setup(self): def setup(self):
super(Function, self).setup() super(Function, self).setup()
if hasattr(self, "_request"): #if hasattr(self, "_request"):
self._request._callsetup() # self._request._callsetup()
fillfuncargs(self) fillfuncargs(self)
def __eq__(self, other): def __eq__(self, other):
@ -1054,6 +1060,7 @@ class FuncargRequest:
"""add finalizer/teardown function to be called after the """add finalizer/teardown function to be called after the
last test within the requesting test context finished last test within the requesting test context finished
execution. """ execution. """
# XXX usually this method is shadowed by factorydef specific ones
self._addfinalizer(finalizer, scope=self.scope) self._addfinalizer(finalizer, scope=self.scope)
def _addfinalizer(self, finalizer, scope): def _addfinalizer(self, finalizer, scope):
@ -1084,13 +1091,11 @@ class FuncargRequest:
def _fillfuncargs(self): def _fillfuncargs(self):
item = self._pyfuncitem item = self._pyfuncitem
funcargnames = getattr(item, "funcargnames", self.funcargnames) funcargnames = getattr(item, "funcargnames", self.funcargnames)
for argname in funcargnames: for argname in funcargnames:
if argname not in item.funcargs: if argname not in item.funcargs:
item.funcargs[argname] = self.getfuncargvalue(argname) item.funcargs[argname] = self.getfuncargvalue(argname)
def _callsetup(self):
self.funcargmanager.ensure_setupcalls(self)
def cached_setup(self, setup, teardown=None, scope="module", extrakey=None): def cached_setup(self, setup, teardown=None, scope="module", extrakey=None):
""" (deprecated) Return a testing resource managed by ``setup`` & """ (deprecated) Return a testing resource managed by ``setup`` &
``teardown`` calls. ``scope`` and ``extrakey`` determine when the ``teardown`` calls. ``scope`` and ``extrakey`` determine when the
@ -1154,20 +1159,19 @@ class FuncargRequest:
factorydef = factorydeflist.pop() factorydef = factorydeflist.pop()
self._factorystack.append(factorydef) self._factorystack.append(factorydef)
try: try:
return self._getfuncargvalue(factorydef) result = self._getfuncargvalue(factorydef)
self._funcargs[argname] = result
return result
finally: finally:
self._factorystack.pop() self._factorystack.pop()
def _getfuncargvalue(self, factorydef): def _getfuncargvalue(self, factorydef):
# collect funcargs from the factory if factorydef.active:
newnames = factorydef.funcargnames return factorydef.cached_result
argname = factorydef.argname
factory_kwargs = {}
def fillfactoryargs():
for newname in newnames:
val = self.getfuncargvalue(newname)
factory_kwargs[newname] = val
# prepare request scope and param attributes before
# calling into factory
argname = factorydef.argname
node = self._pyfuncitem node = self._pyfuncitem
mp = monkeypatch() mp = monkeypatch()
mp.setattr(self, '_currentarg', argname) mp.setattr(self, '_currentarg', argname)
@ -1177,9 +1181,7 @@ class FuncargRequest:
pass pass
else: else:
mp.setattr(self, 'param', param, raising=False) mp.setattr(self, 'param', param, raising=False)
scope = factorydef.scope scope = factorydef.scope
funcargfactory = factorydef.func
if scope is not None: if scope is not None:
__tracebackhide__ = True __tracebackhide__ = True
if scopemismatch(self.scope, scope): if scopemismatch(self.scope, scope):
@ -1191,17 +1193,16 @@ class FuncargRequest:
(scope, argname, self.scope, "\n".join(lines)))) (scope, argname, self.scope, "\n".join(lines))))
__tracebackhide__ = False __tracebackhide__ = False
mp.setattr(self, "scope", scope) mp.setattr(self, "scope", scope)
kwargs = {}
if hasattr(self, "param"): # prepare finalization according to scope
kwargs["extrakey"] = param self.session._setupstate.addfinalizer(factorydef.finish, self.node)
fillfactoryargs() self.funcargmanager.addargfinalizer(factorydef.finish, argname)
val = self.cached_setup(lambda: funcargfactory(**factory_kwargs), for subargname in factorydef.funcargnames: # XXX all deps?
scope=scope, **kwargs) self.funcargmanager.addargfinalizer(factorydef.finish, subargname)
else: mp.setattr(self, "addfinalizer", factorydef.addfinalizer)
fillfactoryargs() # finally perform the factory call
val = funcargfactory(**factory_kwargs) val = factorydef.execute(request=self)
mp.undo() mp.undo()
self._funcargs[argname] = val
return val return val
def _factorytraceback(self): def _factorytraceback(self):
@ -1291,8 +1292,8 @@ class FuncargManager:
self.arg2facspec = {} self.arg2facspec = {}
self._seenplugins = set() self._seenplugins = set()
self._holderobjseen = set() self._holderobjseen = set()
self.setuplist = []
self._arg2finish = {} self._arg2finish = {}
self._autofixtures = []
session.config.pluginmanager.register(self, "funcmanage") session.config.pluginmanager.register(self, "funcmanage")
### XXX this hook should be called for historic events like pytest_configure ### XXX this hook should be called for historic events like pytest_configure
@ -1325,13 +1326,11 @@ class FuncargManager:
# so that the caller can reuse it and does not have to re-discover # so that the caller can reuse it and does not have to re-discover
# factories again for each funcargname # factories again for each funcargname
parentid = parentnode.nodeid parentid = parentnode.nodeid
funcargnames = list(funcargnames) funcargnames = self._autofixtures + list(funcargnames)
_, setupargs = self.getsetuplist(parentnode)
def merge(otherlist): def merge(otherlist):
for arg in otherlist: for arg in otherlist:
if arg not in funcargnames: if arg not in funcargnames:
funcargnames.append(arg) funcargnames.append(arg)
merge(setupargs)
arg2facdeflist = {} arg2facdeflist = {}
lastlen = -1 lastlen = -1
while lastlen != len(funcargnames): while lastlen != len(funcargnames):
@ -1365,6 +1364,9 @@ class FuncargManager:
cs1 = item.callspec cs1 = item.callspec
except AttributeError: except AttributeError:
return return
# determine which fixtures are not needed anymore for the next test
keylist = []
for name in cs1.params: for name in cs1.params:
try: try:
if name in nextitem.callspec.params and \ if name in nextitem.callspec.params and \
@ -1372,8 +1374,13 @@ class FuncargManager:
continue continue
except AttributeError: except AttributeError:
pass pass
key = (name, cs1.params[name]) key = (-cs1._arg2scopenum[name], name, cs1.params[name])
item.session._setupstate._callfinalizers(key) keylist.append(key)
# sort by scope (function scope first, then higher ones)
keylist.sort()
for (scopenum, name, param) in keylist:
item.session._setupstate._callfinalizers((name, param))
l = self._arg2finish.get(name) l = self._arg2finish.get(name)
if l is not None: if l is not None:
for fin in l: for fin in l:
@ -1382,55 +1389,36 @@ class FuncargManager:
def _parsefactories(self, holderobj, nodeid, unittest=False): def _parsefactories(self, holderobj, nodeid, unittest=False):
if holderobj in self._holderobjseen: if holderobj in self._holderobjseen:
return return
#print "parsefactories", holderobj
self._holderobjseen.add(holderobj) self._holderobjseen.add(holderobj)
for name in dir(holderobj): for name in dir(holderobj):
#print "check", holderobj, name
obj = getattr(holderobj, name) obj = getattr(holderobj, name)
if not callable(obj): if not callable(obj):
continue continue
# resource factories either have a pytest_funcarg__ prefix # fixture functions have a pytest_funcarg__ prefix
# or are "funcarg" marked # or are "@pytest.fixture" marked
marker = getattr(obj, "_pytestfixturefunction", None) marker = getattr(obj, "_pytestfixturefunction", None)
if marker is not None: if marker is None:
if not isinstance(marker, FixtureFunctionMarker): if not name.startswith(self._argprefix):
# magic globals with __getattr__
# give us something thats wrong for that case
continue continue
assert not name.startswith(self._argprefix) marker = defaultfuncargprefixmarker
argname = name name = name[len(self._argprefix):]
scope = marker.scope elif not isinstance(marker, FixtureFunctionMarker):
params = marker.params # magic globals with __getattr__ might have got us a wrong
elif name.startswith(self._argprefix): # fixture attribute
argname = name[len(self._argprefix):]
scope = None
params = None
else:
# no funcargs. check if we have a setup function.
setup = getattr(obj, "_pytestsetup", None)
if setup is not None:
scope = setup.scope
sf = SetupCall(self, nodeid, obj, scope, unittest)
self.setuplist.append(sf)
continue continue
faclist = self.arg2facspec.setdefault(argname, []) else:
factorydef = FactoryDef(self, nodeid, argname, obj, scope, params) assert not name.startswith(self._argprefix)
factorydef = FactoryDef(self, nodeid, name, obj,
marker.scope, marker.params,
unittest=unittest)
faclist = self.arg2facspec.setdefault(name, [])
faclist.append(factorydef) faclist.append(factorydef)
### check scope/params mismatch? if marker.autoactive:
# make sure the self._autofixtures list is always sorted
def getsetuplist(self, node): # by scope, scopenum 0 is session
nodeid = node.nodeid self._autofixtures.append(name)
l = [] self._autofixtures.sort(
allargnames = [] key=lambda x: self.arg2facspec[x][-1].scopenum)
for setupcall in self.setuplist:
if nodeid.startswith(setupcall.baseid):
l.append(setupcall)
for arg in setupcall.funcargnames:
if arg not in allargnames:
allargnames.append(arg)
l.sort(key=lambda x: x.scopenum)
return l, allargnames
def getfactorylist(self, argname, nodeid): def getfactorylist(self, argname, nodeid):
try: try:
@ -1438,20 +1426,17 @@ class FuncargManager:
except KeyError: except KeyError:
return None return None
else: else:
return self._matchfactories(factorydeflist, nodeid) return list(self._matchfactories(factorydeflist, nodeid))
def _matchfactories(self, factorydeflist, nodeid): def _matchfactories(self, factorydeflist, nodeid):
l = []
for factorydef in factorydeflist: for factorydef in factorydeflist:
#print "check", basepath, nodeid
if nodeid.startswith(factorydef.baseid): if nodeid.startswith(factorydef.baseid):
l.append(factorydef) yield factorydef
return l
def _raiselookupfailed(self, argname, function, nodeid, getfactb=None): def _raiselookupfailed(self, argname, function, nodeid, getfactb=None):
available = [] available = []
for name, facdef in self.arg2facspec.items(): for name, facdef in self.arg2facspec.items():
faclist = self._matchfactories(facdef, nodeid) faclist = list(self._matchfactories(facdef, nodeid))
if faclist: if faclist:
available.append(name) available.append(name)
msg = "LookupError: no factory found for argument %r" % (argname,) msg = "LookupError: no factory found for argument %r" % (argname,)
@ -1460,36 +1445,6 @@ class FuncargManager:
lines = getfactb and getfactb() or [] lines = getfactb and getfactb() or []
raise FuncargLookupError(function, msg, lines) raise FuncargLookupError(function, msg, lines)
def ensure_setupcalls(self, request):
setuplist, allnames = self.getsetuplist(request._pyfuncitem)
for setupcall in setuplist:
if setupcall.active:
continue
request._factorystack.append(setupcall)
mp = monkeypatch()
try:
mp.setattr(request, "scope", setupcall.scope)
kwargs = {}
for name in setupcall.funcargnames:
kwargs[name] = request.getfuncargvalue(name)
scope = setupcall.scope or "function"
scol = setupcall.scopeitem = request._getscopeitem(scope)
self.session._setupstate.addfinalizer(setupcall.finish, scol)
for argname in setupcall.funcargnames: # XXX all deps?
self.addargfinalizer(setupcall.finish, argname)
req = kwargs.get("request", None)
if req is not None:
mp.setattr(req, "addfinalizer", setupcall.addfinalizer)
# for unittest-setup methods we need to provide
# the correct instance
posargs = ()
if setupcall.unittest:
posargs = (request.instance,)
setupcall.execute(posargs, kwargs)
finally:
mp.undo()
request._factorystack.remove(setupcall)
def addargfinalizer(self, finalizer, argname): def addargfinalizer(self, finalizer, argname):
l = self._arg2finish.setdefault(argname, []) l = self._arg2finish.setdefault(argname, [])
l.append(finalizer) l.append(finalizer)
@ -1501,28 +1456,24 @@ class FuncargManager:
except ValueError: except ValueError:
pass pass
class FactoryDef:
class SetupCall: """ A container for a factory definition. """
""" a container/helper for managing calls to setup functions. """ def __init__(self, funcargmanager, baseid, argname, func, scope, params,
def __init__(self, funcargmanager, baseid, func, scope, unittest): unittest=False):
self.funcargmanager = funcargmanager self.funcargmanager = funcargmanager
self.baseid = baseid self.baseid = baseid
self.func = func self.func = func
self.argname = argname
self.scope = scope
self.scopenum = scopes.index(scope or "function")
self.params = params
startindex = unittest and 1 or None startindex = unittest and 1 or None
self.funcargnames = getfuncargnames(func, startindex=startindex) self.funcargnames = getfuncargnames(func, startindex=startindex)
self.scope = scope self.unittest = unittest
self.scopenum = scopes.index(scope)
self.active = False self.active = False
self.unittest= unittest
self._finalizer = [] self._finalizer = []
def execute(self, posargs, kwargs):
assert not self.active
self.active = True
self.func(*posargs, **kwargs)
def addfinalizer(self, finalizer): def addfinalizer(self, finalizer):
assert self.active
self._finalizer.append(finalizer) self._finalizer.append(finalizer)
def finish(self): def finish(self):
@ -1532,17 +1483,23 @@ class SetupCall:
# check neccesity of next commented call # check neccesity of next commented call
self.funcargmanager.removefinalizer(self.finish) self.funcargmanager.removefinalizer(self.finish)
self.active = False self.active = False
#print "finished", self
#del self.cached_result
class FactoryDef: def execute(self, request):
""" A container for a factory definition. """ kwargs = {}
def __init__(self, funcargmanager, baseid, argname, func, scope, params): for newname in self.funcargnames:
self.funcargmanager = funcargmanager kwargs[newname] = request.getfuncargvalue(newname)
self.baseid = baseid if self.unittest:
self.func = func result = self.func(request.instance, **kwargs)
self.argname = argname else:
self.scope = scope result = self.func(**kwargs)
self.params = params self.active = True
self.funcargnames = getfuncargnames(func) self.cached_result = result
return result
def __repr__(self):
return "<FactoryDef name=%r scope=%r>" % (self.argname, self.scope)
def getfuncargnames(function, startindex=None): def getfuncargnames(function, startindex=None):
# XXX merge with main.py's varnames # XXX merge with main.py's varnames
@ -1634,5 +1591,5 @@ def getfuncargparams(item, ignore, scopenum, cache):
def xunitsetup(obj, name): def xunitsetup(obj, name):
meth = getattr(obj, name, None) meth = getattr(obj, name, None)
if meth is not None: if meth is not None:
if not hasattr(meth, "_pytestsetup"): if not hasattr(meth, "_pytestfixturefunction"):
return meth return meth

View File

@ -52,6 +52,9 @@ class UnitTestCase(pytest.Class):
class TestCaseFunction(pytest.Function): class TestCaseFunction(pytest.Function):
_excinfo = None _excinfo = None
def _getfixturenames(self):
return list(self.session.funcargmanager._autofixtures)
def setup(self): def setup(self):
self._testcase = self.parent.obj(self.name) self._testcase = self.parent.obj(self.name)
self._obj = getattr(self._testcase, self.name) self._obj = getattr(self._testcase, self.name)
@ -62,7 +65,7 @@ class TestCaseFunction(pytest.Function):
if hasattr(self._testcase, 'setup_method'): if hasattr(self._testcase, 'setup_method'):
self._testcase.setup_method(self._obj) self._testcase.setup_method(self._obj)
if hasattr(self, "_request"): if hasattr(self, "_request"):
self._request._callsetup() self._request._fillfuncargs()
def teardown(self): def teardown(self):
if hasattr(self._testcase, 'teardown_method'): if hasattr(self._testcase, 'teardown_method'):

View File

@ -276,8 +276,10 @@ class TestFunction:
assert hasattr(modcol.obj, 'test_func') assert hasattr(modcol.obj, 'test_func')
def test_function_equality(self, testdir, tmpdir): def test_function_equality(self, testdir, tmpdir):
from _pytest.python import FuncargManager
config = testdir.parseconfigure() config = testdir.parseconfigure()
session = testdir.Session(config) session = testdir.Session(config)
session.funcargmanager = FuncargManager(session)
def func1(): def func1():
pass pass
def func2(): def func2():
@ -576,21 +578,18 @@ class TestFillFuncArgs:
assert item.funcargs['other'] == 42 assert item.funcargs['other'] == 42
def test_funcarg_lookup_modulelevel(self, testdir): def test_funcarg_lookup_modulelevel(self, testdir):
modcol = testdir.getmodulecol(""" testdir.makepyfile("""
def pytest_funcarg__something(request): def pytest_funcarg__something(request):
return request.function.__name__ return request.function.__name__
class TestClass: class TestClass:
def test_method(self, something): def test_method(self, something):
pass assert something == "test_method"
def test_func(something): def test_func(something):
pass assert something == "test_func"
""") """)
item1, item2 = testdir.genitems([modcol]) reprec = testdir.inline_run()
funcargs.fillfuncargs(item1) reprec.assertoutcome(passed=2)
assert item1.funcargs['something'] == "test_method"
funcargs.fillfuncargs(item2)
assert item2.funcargs['something'] == "test_func"
def test_funcarg_lookup_classlevel(self, testdir): def test_funcarg_lookup_classlevel(self, testdir):
p = testdir.makepyfile(""" p = testdir.makepyfile("""
@ -1881,16 +1880,9 @@ class TestSetupDiscovery:
def test_parsefactories_conftest(self, testdir): def test_parsefactories_conftest(self, testdir):
testdir.makepyfile(""" testdir.makepyfile("""
def test_check_setup(item, fm): def test_check_setup(item, fm):
setupcalls, allnames = fm.getsetuplist(item) assert len(fm._autofixtures) == 2
assert len(setupcalls) == 2 assert "perfunction2" in fm._autofixtures
assert setupcalls[0].func.__name__ == "perfunction" assert "perfunction" in fm._autofixtures
assert "request" in setupcalls[0].funcargnames
assert "tmpdir" in setupcalls[0].funcargnames
assert setupcalls[1].func.__name__ == "perfunction2"
assert "request" not in setupcalls[1].funcargnames
assert "arg1" in setupcalls[1].funcargnames
assert "tmpdir" not in setupcalls[1].funcargnames
#assert "tmpdir" in setupcalls[1].depfuncargs
""") """)
reprec = testdir.inline_run("-s") reprec = testdir.inline_run("-s")
reprec.assertoutcome(passed=1) reprec.assertoutcome(passed=1)
@ -2098,8 +2090,8 @@ class TestSetupManagement:
class TestClass: class TestClass:
@pytest.setup(scope="class") @pytest.setup(scope="class")
def addteardown(self, item, request): def addteardown(self, item, request):
request.addfinalizer(lambda: l.append("teardown-%d" % item))
l.append("setup-%d" % item) l.append("setup-%d" % item)
request.addfinalizer(lambda: l.append("teardown-%d" % item))
def test_step1(self, item): def test_step1(self, item):
l.append("step1-%d" % item) l.append("step1-%d" % item)
def test_step2(self, item): def test_step2(self, item):
@ -2436,17 +2428,18 @@ class TestFuncargMarker:
l.append("test4") l.append("test4")
def test_5(): def test_5():
assert len(l) == 12 * 3 assert len(l) == 12 * 3
import pprint expected = [
pprint.pprint(l)
assert l == [
'create:1', 'test1', 'fin:1', 'create:2', 'test1', 'create:1', 'test1', 'fin:1', 'create:2', 'test1',
'fin:2', 'create:mod1', 'test2', 'create:1', 'test3', 'fin:2', 'create:mod1', 'test2', 'create:1', 'test3',
'fin:1', 'create:2', 'test3', 'fin:2', 'create:1', 'fin:1', 'create:2', 'test3', 'fin:2', 'create:1',
'test4', 'fin:1', 'create:2', 'test4', 'fin:mod1', 'test4', 'fin:1', 'create:2', 'test4', 'fin:2',
'fin:2', 'create:mod2', 'test2', 'create:1', 'test3', 'fin:mod1', 'create:mod2', 'test2', 'create:1', 'test3',
'fin:1', 'create:2', 'test3', 'fin:2', 'create:1', 'fin:1', 'create:2', 'test3', 'fin:2', 'create:1',
'test4', 'fin:1', 'create:2', 'test4', 'fin:mod2', 'test4', 'fin:1', 'create:2', 'test4', 'fin:2',
'fin:2'] 'fin:mod2']
import pprint
pprint.pprint(list(zip(l, expected)))
assert l == expected
""") """)
reprec = testdir.inline_run("-v") reprec = testdir.inline_run("-v")
reprec.assertoutcome(passed=12+1) reprec.assertoutcome(passed=12+1)
@ -2707,7 +2700,7 @@ def test_request_funcargnames(testdir):
pass pass
def test_function(request, farg): def test_function(request, farg):
assert set(request.funcargnames) == \ assert set(request.funcargnames) == \
set(["tmpdir", "arg1", "request", "farg"]) set(["tmpdir", "sarg", "arg1", "request", "farg"])
""") """)
reprec = testdir.inline_run() reprec = testdir.inline_run()
reprec.assertoutcome(passed=1) reprec.assertoutcome(passed=1)