extend Metafunc and write a pytest_generate_tests hook on the funcarg manager

which discovers factories
This commit is contained in:
holger krekel 2012-07-20 14:16:46 +02:00
parent e14459d45c
commit f358fe7154
3 changed files with 40 additions and 10 deletions

View File

@ -443,6 +443,19 @@ class FuncargManager:
for plugin in plugins: for plugin in plugins:
self.pytest_plugin_registered(plugin) self.pytest_plugin_registered(plugin)
def pytest_generate_tests(self, metafunc):
for argname in metafunc.funcargnames:
faclist = self.getfactorylist(argname, metafunc.parentid,
metafunc.function, raising=False)
if faclist is None:
continue # will raise at setup time
for fac in faclist:
marker = getattr(fac, "funcarg", None)
if marker is not None:
params = marker.kwargs.get("params")
if params is not None:
metafunc.parametrize(argname, params, indirect=True)
def _parsefactories(self, holderobj, nodeid): def _parsefactories(self, holderobj, nodeid):
if holderobj in self._holderobjseen: if holderobj in self._holderobjseen:
return return
@ -456,11 +469,13 @@ class FuncargManager:
obj = getattr(holderobj, name) obj = getattr(holderobj, name)
faclist.append((nodeid, obj)) faclist.append((nodeid, obj))
def getfactorylist(self, argname, nodeid, function): def getfactorylist(self, argname, nodeid, function, raising=True):
try: try:
factorydef = self.arg2facspec[argname] factorydef = self.arg2facspec[argname]
except KeyError: except KeyError:
if raising:
self._raiselookupfailed(argname, function, nodeid) self._raiselookupfailed(argname, function, nodeid)
else:
return self._matchfactories(factorydef, nodeid) return self._matchfactories(factorydef, nodeid)
def _matchfactories(self, factorydef, nodeid): def _matchfactories(self, factorydef, nodeid):

View File

@ -256,7 +256,7 @@ class PyCollector(PyobjMixin, pytest.Collector):
clscol = self.getparent(Class) clscol = self.getparent(Class)
cls = clscol and clscol.obj or None cls = clscol and clscol.obj or None
transfer_markers(funcobj, cls, module) transfer_markers(funcobj, cls, module)
metafunc = Metafunc(funcobj, config=self.config, metafunc = Metafunc(funcobj, parentid=self.nodeid, config=self.config,
cls=cls, module=module) cls=cls, module=module)
gentesthook = self.config.hook.pytest_generate_tests gentesthook = self.config.hook.pytest_generate_tests
extra = [module] extra = [module]
@ -555,10 +555,12 @@ class CallSpec2(object):
class Metafunc: class Metafunc:
def __init__(self, function, config=None, cls=None, module=None): def __init__(self, function, config=None, cls=None, module=None,
parentid=""):
self.config = config self.config = config
self.module = module self.module = module
self.function = function self.function = function
self.parentid = parentid
self.funcargnames = getfuncargnames(function, self.funcargnames = getfuncargnames(function,
startindex=int(cls is not None)) startindex=int(cls is not None))
self.cls = cls self.cls = cls
@ -885,11 +887,6 @@ class FuncargRequest:
self.funcargnames = getfuncargnames(self.function) self.funcargnames = getfuncargnames(self.function)
self.parentid = pyfuncitem.parent.nodeid self.parentid = pyfuncitem.parent.nodeid
def _discoverfactories(self):
for argname in self.funcargnames:
if argname not in self._funcargs:
self._getfaclist(argname)
def _getfaclist(self, argname): def _getfaclist(self, argname):
faclist = self._name2factory.get(argname, None) faclist = self._name2factory.get(argname, None)
if faclist is None: if faclist is None:

View File

@ -989,6 +989,7 @@ class TestMetafunc:
def test_parametrize_functional(self, testdir): def test_parametrize_functional(self, testdir):
testdir.makepyfile(""" testdir.makepyfile("""
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
assert "test_parametrize_functional" in metafunc.parentid
metafunc.parametrize('x', [1,2], indirect=True) metafunc.parametrize('x', [1,2], indirect=True)
metafunc.parametrize('y', [2]) metafunc.parametrize('y', [2])
def pytest_funcarg__x(request): def pytest_funcarg__x(request):
@ -1680,3 +1681,20 @@ class TestFuncargManager:
""") """)
reprec = testdir.inline_run("-s") reprec = testdir.inline_run("-s")
reprec.assertoutcome(passed=1) reprec.assertoutcome(passed=1)
class TestFuncargMarker:
def test_parametrize(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.mark.funcarg(params=["a", "b", "c"])
def pytest_funcarg__arg(request):
return request.param
l = []
def test_param(arg):
l.append(arg)
def test_result():
assert l == list("abc")
""")
reprec = testdir.inline_run()
reprec.assertoutcome(passed=4)