introduce a SetupCall, holding meta information and setup calling state
This commit is contained in:
parent
d68c65b493
commit
b57fb9fd47
|
@ -448,7 +448,7 @@ class FuncargManager:
|
||||||
|
|
||||||
def pytest_generate_tests(self, metafunc):
|
def pytest_generate_tests(self, metafunc):
|
||||||
funcargnames = list(metafunc.funcargnames)
|
funcargnames = list(metafunc.funcargnames)
|
||||||
setuplist, allargnames = self.getsetuplist(metafunc.parentid)
|
_, allargnames = self.getsetuplist(metafunc.parentid)
|
||||||
#print "setuplist, allargnames", setuplist, allargnames
|
#print "setuplist, allargnames", setuplist, allargnames
|
||||||
funcargnames.extend(allargnames)
|
funcargnames.extend(allargnames)
|
||||||
seen = set()
|
seen = set()
|
||||||
|
@ -529,7 +529,9 @@ class FuncargManager:
|
||||||
# no funcargs. check if we have a setup function.
|
# no funcargs. check if we have a setup function.
|
||||||
setup = getattr(obj, "setup", None)
|
setup = getattr(obj, "setup", None)
|
||||||
if setup is not None and isinstance(setup, MarkInfo):
|
if setup is not None and isinstance(setup, MarkInfo):
|
||||||
self.setuplist.append((nodeid, obj))
|
scope = setup.kwargs.get("scope")
|
||||||
|
sf = SetupCall(self, nodeid, obj, scope)
|
||||||
|
self.setuplist.append(sf)
|
||||||
continue
|
continue
|
||||||
faclist = self.arg2facspec.setdefault(argname, [])
|
faclist = self.arg2facspec.setdefault(argname, [])
|
||||||
faclist.append((nodeid, obj))
|
faclist.append((nodeid, obj))
|
||||||
|
@ -537,12 +539,10 @@ class FuncargManager:
|
||||||
def getsetuplist(self, nodeid):
|
def getsetuplist(self, nodeid):
|
||||||
l = []
|
l = []
|
||||||
allargnames = set()
|
allargnames = set()
|
||||||
for baseid, setup in self.setuplist:
|
for setupcall in self.setuplist:
|
||||||
#print "check", baseid, setup
|
if nodeid.startswith(setupcall.baseid):
|
||||||
if nodeid.startswith(baseid):
|
l.append(setupcall)
|
||||||
funcargnames = getfuncargnames(setup)
|
allargnames.update(setupcall.funcargnames)
|
||||||
l.append((setup, funcargnames))
|
|
||||||
allargnames.update(funcargnames)
|
|
||||||
return l, allargnames
|
return l, allargnames
|
||||||
|
|
||||||
|
|
||||||
|
@ -575,6 +575,33 @@ class FuncargManager:
|
||||||
raise FuncargLookupError(function, msg)
|
raise FuncargLookupError(function, msg)
|
||||||
|
|
||||||
|
|
||||||
|
class SetupCall:
|
||||||
|
""" a container/helper for managing calls to setup functions. """
|
||||||
|
def __init__(self, funcargmanager, baseid, func, scope):
|
||||||
|
self.funcargmanager = funcargmanager
|
||||||
|
self.baseid = baseid
|
||||||
|
self.func = func
|
||||||
|
self.funcargnames = getfuncargnames(func)
|
||||||
|
self.scope = scope
|
||||||
|
self.active = False
|
||||||
|
self._finalizer = []
|
||||||
|
|
||||||
|
def execute(self, kwargs):
|
||||||
|
#assert not self.active
|
||||||
|
self.active = True
|
||||||
|
mp = monkeypatch()
|
||||||
|
#if "request" in kwargs:
|
||||||
|
# request = kwargs["request"]
|
||||||
|
# def addfinalizer(func):
|
||||||
|
# #scopeitem = request._getscopeitem(scope)
|
||||||
|
# self._finalizer.append(func)
|
||||||
|
# mp.setattr(request, "addfinalizer", addfinalizer)
|
||||||
|
try:
|
||||||
|
self.func(**kwargs)
|
||||||
|
finally:
|
||||||
|
mp.undo()
|
||||||
|
|
||||||
|
|
||||||
class NoMatch(Exception):
|
class NoMatch(Exception):
|
||||||
""" raised if matching cannot locate a matching names. """
|
""" raised if matching cannot locate a matching names. """
|
||||||
|
|
||||||
|
@ -853,3 +880,8 @@ def getfuncargnames(function, startindex=None):
|
||||||
if numdefaults:
|
if numdefaults:
|
||||||
return argnames[startindex:-numdefaults]
|
return argnames[startindex:-numdefaults]
|
||||||
return argnames[startindex:]
|
return argnames[startindex:]
|
||||||
|
|
||||||
|
def readscope(func, markattr):
|
||||||
|
marker = getattr(func, markattr, None)
|
||||||
|
if marker is not None:
|
||||||
|
return marker.kwargs.get("scope")
|
||||||
|
|
|
@ -3,7 +3,7 @@ import py
|
||||||
import inspect
|
import inspect
|
||||||
import sys
|
import sys
|
||||||
import pytest
|
import pytest
|
||||||
from _pytest.main import getfslineno, getfuncargnames
|
from _pytest.main import getfslineno, getfuncargnames, readscope
|
||||||
from _pytest.monkeypatch import monkeypatch
|
from _pytest.monkeypatch import monkeypatch
|
||||||
|
|
||||||
import _pytest
|
import _pytest
|
||||||
|
@ -1003,21 +1003,21 @@ class FuncargRequest:
|
||||||
setuplist, allnames = self.funcargmanager.getsetuplist(
|
setuplist, allnames = self.funcargmanager.getsetuplist(
|
||||||
self._pyfuncitem.nodeid)
|
self._pyfuncitem.nodeid)
|
||||||
mp = monkeypatch()
|
mp = monkeypatch()
|
||||||
for setupfunc, funcargnames in setuplist:
|
for setupcall in setuplist:
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
for name in funcargnames:
|
for name in setupcall.funcargnames:
|
||||||
if name == "request":
|
if name == "request":
|
||||||
kwargs[name] = self
|
kwargs[name] = self
|
||||||
else:
|
else:
|
||||||
kwargs[name] = self.getfuncargvalue(name)
|
kwargs[name] = self.getfuncargvalue(name)
|
||||||
|
|
||||||
scope = readscope(setupfunc, "setup")
|
mp.setattr(self, 'scope', setupcall.scope)
|
||||||
mp.setattr(self, 'scope', scope)
|
|
||||||
try:
|
try:
|
||||||
if scope is None:
|
if setupcall.scope is None:
|
||||||
setupfunc(**kwargs)
|
setupcall.execute(kwargs)
|
||||||
else:
|
else:
|
||||||
self.cached_setup(lambda: setupfunc(**kwargs), scope=scope)
|
self.cached_setup(lambda: setupcall.execute(kwargs),
|
||||||
|
scope=setupcall.scope)
|
||||||
finally:
|
finally:
|
||||||
mp.undo()
|
mp.undo()
|
||||||
|
|
||||||
|
@ -1140,7 +1140,3 @@ def slice_kwargs(names, kwargs):
|
||||||
new_kwargs[name] = kwargs[name]
|
new_kwargs[name] = kwargs[name]
|
||||||
return new_kwargs
|
return new_kwargs
|
||||||
|
|
||||||
def readscope(func, markattr):
|
|
||||||
marker = getattr(func, markattr, None)
|
|
||||||
if marker is not None:
|
|
||||||
return marker.kwargs.get("scope")
|
|
||||||
|
|
|
@ -1752,10 +1752,14 @@ class TestSetupDiscovery:
|
||||||
testdir.makeconftest("""
|
testdir.makeconftest("""
|
||||||
import pytest
|
import pytest
|
||||||
@pytest.mark.setup
|
@pytest.mark.setup
|
||||||
def perfunction(request):
|
def perfunction(request, tmpdir):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@pytest.mark.funcarg
|
||||||
|
def arg1(request, tmpdir):
|
||||||
pass
|
pass
|
||||||
@pytest.mark.setup
|
@pytest.mark.setup
|
||||||
def perfunction2(request):
|
def perfunction2(request, arg1):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def pytest_funcarg__fm(request):
|
def pytest_funcarg__fm(request):
|
||||||
|
@ -1769,12 +1773,16 @@ 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):
|
||||||
setuplist, allnames = fm.getsetuplist(item.nodeid)
|
setupcalls, allnames = fm.getsetuplist(item.nodeid)
|
||||||
assert len(setuplist) == 2
|
assert len(setupcalls) == 2
|
||||||
assert setuplist[0][0].__name__ == "perfunction"
|
assert setupcalls[0].func.__name__ == "perfunction"
|
||||||
assert "request" in setuplist[0][1]
|
assert "request" in setupcalls[0].funcargnames
|
||||||
assert setuplist[1][0].__name__ == "perfunction2"
|
assert "tmpdir" in setupcalls[0].funcargnames
|
||||||
assert "request" in setuplist[1][1]
|
assert setupcalls[1].func.__name__ == "perfunction2"
|
||||||
|
assert "request" 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)
|
||||||
|
|
Loading…
Reference in New Issue