rename a number of internal and externally visible variables to use the fixture name

rather than funcargs.  Introduce .funcargnames compatibility attribute for backward compat.
This commit is contained in:
holger krekel 2012-10-05 14:24:44 +02:00
parent 8282efbb40
commit bb07ba7807
33 changed files with 281 additions and 261 deletions

View File

@ -71,7 +71,7 @@ introduction of this new method needs to be _fully_ backward compatible -
and the documentation needs to change along to mention this new way of and the documentation needs to change along to mention this new way of
doing things. doing things.
impl note: probably Request._fillfuncargs would be called from the impl note: probably Request._fillfixtures would be called from the
python plugins own pytest_runtest_setup(item) and would call python plugins own pytest_runtest_setup(item) and would call
item.getresource(X) for all X in the funcargs of a function. item.getresource(X) for all X in the funcargs of a function.

View File

@ -189,7 +189,7 @@ def pytest_funcarg__capsys(request):
""" """
if "capfd" in request._funcargs: if "capfd" in request._funcargs:
raise request.raiseerror(error_capsysfderror) raise request.raiseerror(error_capsysfderror)
return CaptureFuncarg(py.io.StdCapture) return CaptureFixture(py.io.StdCapture)
def pytest_funcarg__capfd(request): def pytest_funcarg__capfd(request):
"""enables capturing of writes to file descriptors 1 and 2 and makes """enables capturing of writes to file descriptors 1 and 2 and makes
@ -200,9 +200,9 @@ def pytest_funcarg__capfd(request):
request.raiseerror(error_capsysfderror) request.raiseerror(error_capsysfderror)
if not hasattr(os, 'dup'): if not hasattr(os, 'dup'):
pytest.skip("capfd funcarg needs os.dup") pytest.skip("capfd funcarg needs os.dup")
return CaptureFuncarg(py.io.StdCaptureFD) return CaptureFixture(py.io.StdCaptureFD)
class CaptureFuncarg: class CaptureFixture:
def __init__(self, captureclass): def __init__(self, captureclass):
self.capture = captureclass(now=False) self.capture = captureclass(now=False)

View File

@ -80,7 +80,7 @@ def showhelp(config):
tw.line() ; tw.line() tw.line() ; tw.line()
#tw.sep("=") #tw.sep("=")
tw.line("to see available markers type: py.test --markers") tw.line("to see available markers type: py.test --markers")
tw.line("to see available funcargs type: py.test --funcargs") tw.line("to see available fixtures type: py.test --fixtures")
return return
tw.line("conftest.py options:") tw.line("conftest.py options:")

View File

@ -308,8 +308,8 @@ class Node(object):
pass pass
def _repr_failure_py(self, excinfo, style=None): def _repr_failure_py(self, excinfo, style=None):
fm = self.session.funcargmanager fm = self.session._fixturemanager
if excinfo.errisinstance(fm.FuncargLookupError): if excinfo.errisinstance(fm.FixtureLookupError):
function = excinfo.value.function function = excinfo.value.function
factblines = excinfo.value.factblines factblines = excinfo.value.factblines
if function is not None: if function is not None:
@ -317,7 +317,7 @@ class Node(object):
lines, _ = inspect.getsourcelines(function) lines, _ = inspect.getsourcelines(function)
for i, line in enumerate(lines): for i, line in enumerate(lines):
if line.strip().startswith('def'): if line.strip().startswith('def'):
return fm.FuncargLookupErrorRepr(fspath, return fm.FixtureLookupErrorRepr(fspath,
lineno, lines[:i+1], lineno, lines[:i+1],
str(excinfo.value.msg), factblines) str(excinfo.value.msg), factblines)
if self.config.option.fulltrace: if self.config.option.fulltrace:

View File

@ -44,18 +44,7 @@ defaultfuncargprefixmarker = fixture()
# XXX remove in favour of fixture(autoactive=True) # 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 """ alias for fixture(scope, autoactive=True) """
a testcontext. A fixture function is executed for each scope and may
receive funcargs which allows it to initialise and provide implicit
test state. A fixture function may receive the "testcontext" object
and register a finalizer via "testcontext.addfinalizer(finalizer)"
which will be called when the last test in the testcontext has
executed.
:arg scope: the scope for which the setup function will be active, one
of "function", "class", "module", "session".
Defaults to "function".
"""
return FixtureFunctionMarker(scope, params=None, autoactive=True) return FixtureFunctionMarker(scope, params=None, autoactive=True)
def cached_property(f): def cached_property(f):
@ -85,9 +74,9 @@ def pyobj_property(name):
def pytest_addoption(parser): def pytest_addoption(parser):
group = parser.getgroup("general") group = parser.getgroup("general")
group.addoption('--funcargs', group.addoption('--fixtures', '--fixtures',
action="store_true", dest="showfuncargs", default=False, action="store_true", dest="showfixtures", default=False,
help="show available function arguments, sorted by plugin") help="show available fixtures, sorted by plugin appearance")
parser.addini("python_files", type="args", parser.addini("python_files", type="args",
default=('test_*.py', '*_test.py'), default=('test_*.py', '*_test.py'),
help="glob-style file patterns for Python test module discovery") help="glob-style file patterns for Python test module discovery")
@ -97,8 +86,8 @@ def pytest_addoption(parser):
help="prefixes for Python test function and method discovery") help="prefixes for Python test function and method discovery")
def pytest_cmdline_main(config): def pytest_cmdline_main(config):
if config.option.showfuncargs: if config.option.showfixtures:
showfuncargs(config) showfixtures(config)
return 0 return 0
@ -119,7 +108,7 @@ def pytest_configure(config):
) )
def pytest_sessionstart(session): def pytest_sessionstart(session):
session.funcargmanager = FuncargManager(session) session._fixturemanager = FixtureManager(session)
@pytest.mark.trylast @pytest.mark.trylast
def pytest_namespace(): def pytest_namespace():
@ -131,10 +120,11 @@ def pytest_namespace():
'collect': { 'collect': {
'Module': Module, 'Class': Class, 'Instance': Instance, 'Module': Module, 'Class': Class, 'Instance': Instance,
'Function': Function, 'Generator': Generator, 'Function': Function, 'Generator': Generator,
'_fillfuncargs': fillfuncargs} '_fillfuncargs': fillfixtures}
} }
def pytest_funcarg__pytestconfig(request): @fixture()
def pytestconfig(request):
""" the pytest config object with access to command line opts.""" """ the pytest config object with access to command line opts."""
return request.config return request.config
@ -146,12 +136,12 @@ def pytest_pyfunc_call(__multicall__, pyfuncitem):
testfunction(*pyfuncitem._args) testfunction(*pyfuncitem._args)
else: else:
try: try:
funcargnames = pyfuncitem.funcargnames fixturenames = pyfuncitem.fixturenames
except AttributeError: except AttributeError:
funcargs = pyfuncitem.funcargs funcargs = pyfuncitem.funcargs
else: else:
funcargs = {} funcargs = {}
for name in funcargnames: for name in fixturenames:
funcargs[name] = pyfuncitem.funcargs[name] funcargs[name] = pyfuncitem.funcargs[name]
testfunction(**funcargs) testfunction(**funcargs)
@ -352,7 +342,7 @@ class Module(pytest.File, PyCollector):
return self._memoizedcall('_obj', self._importtestmodule) return self._memoizedcall('_obj', self._importtestmodule)
def collect(self): def collect(self):
self.session.funcargmanager._parsefactories(self.obj, self.nodeid) self.session._fixturemanager._parsefactories(self.obj, self.nodeid)
return super(Module, self).collect() return super(Module, self).collect()
def _importtestmodule(self): def _importtestmodule(self):
@ -425,7 +415,7 @@ class Instance(PyCollector):
return obj return obj
def collect(self): def collect(self):
self.session.funcargmanager._parsefactories(self.obj, self.nodeid) self.session._fixturemanager._parsefactories(self.obj, self.nodeid)
return super(Instance, self).collect() return super(Instance, self).collect()
def newinstance(self): def newinstance(self):
@ -534,14 +524,14 @@ def hasinit(obj):
def fillfuncargs(function): def fillfixtures(function):
""" fill missing funcargs for a test function. """ """ fill missing funcargs for a test function. """
if getattr(function, "_args", None) is None: # not a yielded function if getattr(function, "_args", None) is None: # not a yielded function
try: try:
request = function._request request = function._request
except AttributeError: except AttributeError:
request = function._request = FuncargRequest(function) request = function._request = FixtureRequest(function)
request._fillfuncargs() request._fillfixtures()
_notexists = object() _notexists = object()
@ -605,21 +595,30 @@ class CallSpec2(object):
self._globalparam = param self._globalparam = param
class Metafunc: class FuncargnamesCompatAttr:
""" helper class so that Metafunc, Function and FixtureRequest
don't need to each define the "funcargnames" compatibility attribute.
"""
@property
def funcargnames(self):
""" alias attribute for ``fixturenames`` for pre-2.3 compatibility"""
return self.fixturenames
class Metafunc(FuncargnamesCompatAttr):
def __init__(self, function, config=None, cls=None, module=None, def __init__(self, function, config=None, cls=None, module=None,
parentnode=None): parentnode=None):
self.config = config self.config = config
self.module = module self.module = module
self.function = function self.function = function
self.parentnode = parentnode self.parentnode = parentnode
self.parentid = getattr(parentnode, "nodeid", "") self._parentid = getattr(parentnode, "nodeid", "")
argnames = getfuncargnames(function, startindex=int(cls is not None)) argnames = getfuncargnames(function, startindex=int(cls is not None))
if parentnode is not None: if parentnode is not None:
fm = parentnode.session.funcargmanager fm = parentnode.session._fixturemanager
self.funcargnames, self._arg2facdeflist = fm.getallfuncargnames( self.fixturenames, self._arg2fixturedeflist = fm.getfixtureclosure(
argnames, parentnode) argnames, parentnode)
else: else:
self.funcargnames = argnames self.fixturenames = argnames
self.cls = cls self.cls = cls
self.module = module self.module = module
self._calls = [] self._calls = []
@ -631,7 +630,7 @@ class Metafunc:
""" Add new invocations to the underlying test function using the list """ Add new invocations to the underlying test function using the list
of argvalues for the given argnames. Parametrization is performed of argvalues for the given argnames. Parametrization is performed
during the collection phase. If you need to setup expensive resources during the collection phase. If you need to setup expensive resources
you may pass indirect=True and implement a funcarg factory which can you may pass indirect=True and implement a fixture function which can
perform the expensive setup just before a test is actually run. perform the expensive setup just before a test is actually run.
:arg argnames: an argument name or a list of argument names :arg argnames: an argument name or a list of argument names
@ -640,7 +639,7 @@ class Metafunc:
values for the list of argument names. values for the list of argument names.
:arg indirect: if True each argvalue corresponding to an argument will :arg indirect: if True each argvalue corresponding to an argument will
be passed as request.param to its respective funcarg factory so be passed as request.param to its respective fixture function so
that it can perform more expensive setups during the setup phase of that it can perform more expensive setups during the setup phase of
a test rather than at collection time. a test rather than at collection time.
@ -657,7 +656,7 @@ class Metafunc:
if not indirect: if not indirect:
#XXX should we also check for the opposite case? #XXX should we also check for the opposite case?
for arg in argnames: for arg in argnames:
if arg not in self.funcargnames: if arg not in self.fixturenames:
raise ValueError("%r has no argument %r" %(self.function, arg)) raise ValueError("%r has no argument %r" %(self.function, arg))
valtype = indirect and "params" or "funcargs" valtype = indirect and "params" or "funcargs"
if not ids: if not ids:
@ -686,13 +685,13 @@ class Metafunc:
:arg id: used for reporting and identification purposes. If you :arg id: used for reporting and identification purposes. If you
don't supply an `id` an automatic unique id will be generated. don't supply an `id` an automatic unique id will be generated.
:arg param: a parameter which will be exposed to a later funcarg factory :arg param: a parameter which will be exposed to a later fixture function
invocation through the ``request.param`` attribute. invocation through the ``request.param`` attribute.
""" """
assert funcargs is None or isinstance(funcargs, dict) assert funcargs is None or isinstance(funcargs, dict)
if funcargs is not None: if funcargs is not None:
for name in funcargs: for name in funcargs:
if name not in self.funcargnames: if name not in self.fixturenames:
pytest.fail("funcarg %r not used in this function." % name) pytest.fail("funcarg %r not used in this function." % name)
else: else:
funcargs = {} funcargs = {}
@ -722,11 +721,11 @@ class IDMaker:
return "-".join(l) return "-".join(l)
def showfuncargs(config): def showfixtures(config):
from _pytest.main import wrap_session from _pytest.main import wrap_session
return wrap_session(config, _showfuncargs_main) return wrap_session(config, _showfixtures_main)
def _showfuncargs_main(config, session): def _showfixtures_main(config, session):
session.perform_collect() session.perform_collect()
if session.items: if session.items:
plugins = session.items[0].getplugins() plugins = session.items[0].getplugins()
@ -735,7 +734,7 @@ def _showfuncargs_main(config, session):
curdir = py.path.local() curdir = py.path.local()
tw = py.io.TerminalWriter() tw = py.io.TerminalWriter()
verbose = config.getvalue("verbose") verbose = config.getvalue("verbose")
argprefix = session.funcargmanager._argprefix argprefix = session._fixturemanager._argprefix
for plugin in plugins: for plugin in plugins:
available = [] available = []
for name, factory in vars(plugin).items(): for name, factory in vars(plugin).items():
@ -854,7 +853,7 @@ class RaisesContext(object):
# the basic py.test Function item # the basic py.test Function item
# #
_dummy = object() _dummy = object()
class Function(FunctionMixin, pytest.Item): class Function(FunctionMixin, pytest.Item, FuncargnamesCompatAttr):
""" a Function Item is responsible for setting up and executing a """ a Function Item is responsible for setting up and executing a
Python test function. Python test function.
""" """
@ -876,11 +875,11 @@ class Function(FunctionMixin, pytest.Item):
self.param = callspec.param self.param = callspec.param
else: else:
self.funcargs = {} self.funcargs = {}
self._request = req = FuncargRequest(self) self._request = req = FixtureRequest(self)
#req._discoverfactories() #req._discoverfactories()
if callobj is not _dummy: if callobj is not _dummy:
self.obj = callobj self.obj = callobj
self.funcargnames = self._getfixturenames() self.fixturenames = self._getfuncargnames()
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)
@ -888,9 +887,10 @@ class Function(FunctionMixin, pytest.Item):
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):
def _getfuncargnames(self):
startindex = int(self.cls is not None) startindex = int(self.cls is not None)
return (self.session.funcargmanager._autofixtures + return (self.session._fixturemanager._autofixtures +
getfuncargnames(self.obj, startindex=startindex)) getfuncargnames(self.obj, startindex=startindex))
@property @property
@ -921,7 +921,7 @@ class Function(FunctionMixin, pytest.Item):
super(Function, self).setup() super(Function, self).setup()
#if hasattr(self, "_request"): #if hasattr(self, "_request"):
# self._request._callsetup() # self._request._callsetup()
fillfuncargs(self) fillfixtures(self)
def __eq__(self, other): def __eq__(self, other):
try: try:
@ -960,8 +960,8 @@ def scopeproperty(name=None, doc=None):
return decoratescope return decoratescope
class FuncargRequest: class FixtureRequest(FuncargnamesCompatAttr):
""" A request for function arguments from a test or setup function. """ A request for fixtures from a test or setup function.
A request object gives access to attributes of the requesting A request object gives access to attributes of the requesting
test context. It has an optional ``param`` attribute in case test context. It has an optional ``param`` attribute in case
@ -976,38 +976,38 @@ class FuncargRequest:
self.scope = "function" self.scope = "function"
self.getparent = pyfuncitem.getparent self.getparent = pyfuncitem.getparent
self._funcargs = self._pyfuncitem.funcargs.copy() self._funcargs = self._pyfuncitem.funcargs.copy()
self._name2factory = {} self._arg2fixturedeflist = {}
self.funcargmanager = pyfuncitem.session.funcargmanager self._fixturemanager = pyfuncitem.session._fixturemanager
self._currentarg = None self._currentarg = None
self.parentid = pyfuncitem.parent.nodeid self._parentid = pyfuncitem.parent.nodeid
self.funcargnames, self._arg2facdeflist_ = \ self.fixturenames, self._arg2fixturedeflist_ = \
self.funcargmanager.getallfuncargnames( self._fixturemanager.getfixtureclosure(
getfuncargnames(self.function), # XXX _pyfuncitem... getfuncargnames(self.function), # XXX _pyfuncitem...
pyfuncitem.parent) pyfuncitem.parent)
self._factorystack = [] self._fixturestack = []
@property @property
def node(self): def node(self):
""" underlying collection node (depends on request scope)""" """ underlying collection node (depends on request scope)"""
return self._getscopeitem(self.scope) return self._getscopeitem(self.scope)
def _getfaclist(self, argname): def _getfixturedeflist(self, argname):
facdeflist = self._name2factory.get(argname, None) fixturedeflist = self._arg2fixturedeflist.get(argname, None)
getfactb = None getfixturetb = None
function = None function = None
if facdeflist is None: if fixturedeflist is None:
if self._factorystack: if self._fixturestack:
function = self._factorystack[-1].func function = self._fixturestack[-1].func
getfactb = lambda: self._factorystack[:-1] getfixturetb = lambda: self._fixturestack[:-1]
else: else:
function = self.function function = self.function
facdeflist = self.funcargmanager.getfactorylist( fixturedeflist = self._fixturemanager.getfixturedeflist(
argname, self.parentid) argname, self._parentid)
self._name2factory[argname] = facdeflist self._arg2fixturedeflist[argname] = fixturedeflist
if not facdeflist: if not fixturedeflist:
self.funcargmanager._raiselookupfailed(argname, function, self._fixturemanager._raiselookupfailed(argname, function,
self.parentid, getfactb) self._parentid, getfixturetb)
return facdeflist return fixturedeflist
@property @property
def config(self): def config(self):
@ -1060,7 +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 # XXX usually this method is shadowed by fixturedef 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,15 +1084,15 @@ class FuncargRequest:
self.node.applymarker(marker) self.node.applymarker(marker)
def raiseerror(self, msg): def raiseerror(self, msg):
""" raise a FuncargLookupError with the given message. """ """ raise a FixtureLookupError with the given message. """
raise self.funcargmanager.FuncargLookupError(self.function, msg) raise self._fixturemanager.FixtureLookupError(self.function, msg)
def _fillfuncargs(self): def _fillfixtures(self):
item = self._pyfuncitem item = self._pyfuncitem
funcargnames = getattr(item, "funcargnames", self.funcargnames) fixturenames = getattr(item, "fixturenames", self.fixturenames)
for argname in funcargnames: for argname in fixturenames:
if argname not in item.funcargs: if argname not in item.funcargs:
item.funcargs[argname] = self.getfuncargvalue(argname) item.funcargs[argname] = self.getfuncargvalue(argname)
@ -1100,9 +1100,9 @@ class FuncargRequest:
""" (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
``teardown`` function will be called so that subsequent calls to ``teardown`` function will be called so that subsequent calls to
``setup`` would recreate the resource. With pytest-2.3 you ``setup`` would recreate the resource. With pytest-2.3 you often
do not need ``cached_setup()`` as you can directly declare a scope do not need ``cached_setup()`` as you can directly declare a scope
on a funcarg factory and register a finalizer through on a fixture function and register a finalizer through
``request.addfinalizer()``. ``request.addfinalizer()``.
:arg teardown: function receiving a previously setup resource. :arg teardown: function receiving a previously setup resource.
@ -1151,27 +1151,27 @@ class FuncargRequest:
except KeyError: except KeyError:
pass pass
try: try:
factorydeflist = self._getfaclist(argname) fixturedeflist = self._getfixturedeflist(argname)
except FuncargLookupError: except FixtureLookupError:
if argname == "request": if argname == "request":
return self return self
raise raise
factorydef = factorydeflist.pop() fixturedef = fixturedeflist.pop()
self._factorystack.append(factorydef) self._fixturestack.append(fixturedef)
try: try:
result = self._getfuncargvalue(factorydef) result = self._getfuncargvalue(fixturedef)
self._funcargs[argname] = result self._funcargs[argname] = result
return result return result
finally: finally:
self._factorystack.pop() self._fixturestack.pop()
def _getfuncargvalue(self, factorydef): def _getfuncargvalue(self, fixturedef):
if factorydef.active: if fixturedef.active:
return factorydef.cached_result return fixturedef.cached_result
# prepare request scope and param attributes before # prepare request scope and param attributes before
# calling into factory # calling into factory
argname = factorydef.argname argname = fixturedef.argname
node = self._pyfuncitem node = self._pyfuncitem
mp = monkeypatch() mp = monkeypatch()
mp.setattr(self, '_currentarg', argname) mp.setattr(self, '_currentarg', argname)
@ -1181,7 +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 = fixturedef.scope
if scope is not None: if scope is not None:
__tracebackhide__ = True __tracebackhide__ = True
if scopemismatch(self.scope, scope): if scopemismatch(self.scope, scope):
@ -1195,20 +1195,20 @@ class FuncargRequest:
mp.setattr(self, "scope", scope) mp.setattr(self, "scope", scope)
# prepare finalization according to scope # prepare finalization according to scope
self.session._setupstate.addfinalizer(factorydef.finish, self.node) self.session._setupstate.addfinalizer(fixturedef.finish, self.node)
self.funcargmanager.addargfinalizer(factorydef.finish, argname) self._fixturemanager.addargfinalizer(fixturedef.finish, argname)
for subargname in factorydef.funcargnames: # XXX all deps? for subargname in fixturedef.fixturenames: # XXX all deps?
self.funcargmanager.addargfinalizer(factorydef.finish, subargname) self._fixturemanager.addargfinalizer(fixturedef.finish, subargname)
mp.setattr(self, "addfinalizer", factorydef.addfinalizer) mp.setattr(self, "addfinalizer", fixturedef.addfinalizer)
# finally perform the factory call # finally perform the factory call
val = factorydef.execute(request=self) val = fixturedef.execute(request=self)
mp.undo() mp.undo()
return val return val
def _factorytraceback(self): def _factorytraceback(self):
lines = [] lines = []
for factorydef in self._factorystack: for fixturedef in self._fixturestack:
factory = factorydef.func factory = fixturedef.func
fs, lineno = getfslineno(factory) fs, lineno = getfslineno(factory)
p = self._pyfuncitem.session.fspath.bestrelpath(fs) p = self._pyfuncitem.session.fspath.bestrelpath(fs)
args = inspect.formatargspec(*inspect.getargspec(factory)) args = inspect.formatargspec(*inspect.getargspec(factory))
@ -1232,10 +1232,10 @@ class FuncargRequest:
raise ValueError("unknown finalization scope %r" %(scope,)) raise ValueError("unknown finalization scope %r" %(scope,))
def __repr__(self): def __repr__(self):
return "<FuncargRequest for %r>" %(self._pyfuncitem) return "<FixtureRequest for %r>" %(self._pyfuncitem)
class ScopeMismatchError(Exception): class ScopeMismatchError(Exception):
""" A funcarg factory tries to access a funcargvalue/factory """ A fixture function tries to use a different fixture function which
which has a lower scope (e.g. a Session one calls a function one) which has a lower scope (e.g. a Session one calls a function one)
""" """
@ -1249,14 +1249,14 @@ def slice_kwargs(names, kwargs):
new_kwargs[name] = kwargs[name] new_kwargs[name] = kwargs[name]
return new_kwargs return new_kwargs
class FuncargLookupError(LookupError): class FixtureLookupError(LookupError):
""" could not find a factory. """ """ could not find a factory. """
def __init__(self, function, msg, factblines=None): def __init__(self, function, msg, factblines=None):
self.function = function self.function = function
self.msg = msg self.msg = msg
self.factblines = factblines self.factblines = factblines
class FuncargLookupErrorRepr(TerminalRepr): class FixtureLookupErrorRepr(TerminalRepr):
def __init__(self, filename, firstlineno, deflines, errorstring, factblines): def __init__(self, filename, firstlineno, deflines, errorstring, factblines):
self.deflines = deflines self.deflines = deflines
self.errorstring = errorstring self.errorstring = errorstring
@ -1268,10 +1268,10 @@ class FuncargLookupErrorRepr(TerminalRepr):
tw.line() tw.line()
if self.factblines: if self.factblines:
tw.line(' dependency of:') tw.line(' dependency of:')
for factorydef in self.factblines: for fixturedef in self.factblines:
tw.line(' %s in %s' % ( tw.line(' %s in %s' % (
factorydef.argname, fixturedef.argname,
factorydef.baseid, fixturedef.baseid,
)) ))
tw.line() tw.line()
for line in self.deflines: for line in self.deflines:
@ -1281,15 +1281,15 @@ class FuncargLookupErrorRepr(TerminalRepr):
tw.line() tw.line()
tw.line("%s:%d" % (self.filename, self.firstlineno+1)) tw.line("%s:%d" % (self.filename, self.firstlineno+1))
class FuncargManager: class FixtureManager:
_argprefix = "pytest_funcarg__" _argprefix = "pytest_funcarg__"
FuncargLookupError = FuncargLookupError FixtureLookupError = FixtureLookupError
FuncargLookupErrorRepr = FuncargLookupErrorRepr FixtureLookupErrorRepr = FixtureLookupErrorRepr
def __init__(self, session): def __init__(self, session):
self.session = session self.session = session
self.config = session.config self.config = session.config
self.arg2facspec = {} self.arg2fixturedeflist = {}
self._seenplugins = set() self._seenplugins = set()
self._holderobjseen = set() self._holderobjseen = set()
self._arg2finish = {} self._arg2finish = {}
@ -1319,41 +1319,44 @@ class FuncargManager:
for plugin in plugins: for plugin in plugins:
self.pytest_plugin_registered(plugin) self.pytest_plugin_registered(plugin)
def getallfuncargnames(self, funcargnames, parentnode): def getfixtureclosure(self, fixturenames, parentnode):
# collect the closure of all funcargs, starting with # collect the closure of all funcargs, starting with the given
# funcargnames as the initial set # fixturenames as the initial set. As we have to visit all
# we populate and return a arg2facdeflist mapping # factory definitions anyway, we also return a arg2fixturedeflist
# so that the caller can reuse it and does not have to re-discover # mapping so that the caller can reuse it and does not have
# factories again for each funcargname # to re-discover fixturedefs again for each fixturename
# (discovering matching fixtures for a given name/node is expensive)
parentid = parentnode.nodeid parentid = parentnode.nodeid
funcargnames = self._autofixtures + list(funcargnames) fixturenames_closure = list(self._autofixtures)
def merge(otherlist): def merge(otherlist):
for arg in otherlist: for arg in otherlist:
if arg not in funcargnames: if arg not in fixturenames_closure:
funcargnames.append(arg) fixturenames_closure.append(arg)
arg2facdeflist = {} merge(fixturenames)
arg2fixturedeflist = {}
lastlen = -1 lastlen = -1
while lastlen != len(funcargnames): while lastlen != len(fixturenames_closure):
lastlen = len(funcargnames) lastlen = len(fixturenames_closure)
for argname in list(funcargnames): for argname in fixturenames_closure:
if argname in arg2facdeflist: if argname in arg2fixturedeflist:
continue continue
facdeflist = self.getfactorylist(argname, parentid) fixturedeflist = self.getfixturedeflist(argname, parentid)
arg2facdeflist[argname] = facdeflist arg2fixturedeflist[argname] = fixturedeflist
if facdeflist is not None: if fixturedeflist is not None:
for facdef in facdeflist: for fixturedef in fixturedeflist:
merge(facdef.funcargnames) merge(fixturedef.fixturenames)
return funcargnames, arg2facdeflist return fixturenames_closure, arg2fixturedeflist
def pytest_generate_tests(self, metafunc): def pytest_generate_tests(self, metafunc):
for argname in metafunc.funcargnames: for argname in metafunc.fixturenames:
faclist = metafunc._arg2facdeflist[argname] faclist = metafunc._arg2fixturedeflist[argname]
if faclist is None: if faclist is None:
continue # will raise FuncargLookupError at setup time continue # will raise FixtureLookupError at setup time
for facdef in faclist: for fixturedef in faclist:
if facdef.params is not None: if fixturedef.params is not None:
metafunc.parametrize(argname, facdef.params, indirect=True, metafunc.parametrize(argname, fixturedef.params, indirect=True,
scope=facdef.scope) scope=fixturedef.scope)
def pytest_collection_modifyitems(self, items): def pytest_collection_modifyitems(self, items):
# separate parametrized setups # separate parametrized setups
@ -1394,7 +1397,7 @@ class FuncargManager:
obj = getattr(holderobj, name) obj = getattr(holderobj, name)
if not callable(obj): if not callable(obj):
continue continue
# fixture functions have a pytest_funcarg__ prefix # fixture functions have a pytest_funcarg__ prefix (pre-2.3 style)
# or are "@pytest.fixture" marked # or are "@pytest.fixture" marked
marker = getattr(obj, "_pytestfixturefunction", None) marker = getattr(obj, "_pytestfixturefunction", None)
if marker is None: if marker is None:
@ -1408,42 +1411,42 @@ class FuncargManager:
continue continue
else: else:
assert not name.startswith(self._argprefix) assert not name.startswith(self._argprefix)
factorydef = FactoryDef(self, nodeid, name, obj, fixturedef = FixtureDef(self, nodeid, name, obj,
marker.scope, marker.params, marker.scope, marker.params,
unittest=unittest) unittest=unittest)
faclist = self.arg2facspec.setdefault(name, []) faclist = self.arg2fixturedeflist.setdefault(name, [])
faclist.append(factorydef) faclist.append(fixturedef)
if marker.autoactive: if marker.autoactive:
# make sure the self._autofixtures list is always sorted # make sure the self._autofixtures list is always sorted
# by scope, scopenum 0 is session # by scope, scopenum 0 is session
self._autofixtures.append(name) self._autofixtures.append(name)
self._autofixtures.sort( self._autofixtures.sort(
key=lambda x: self.arg2facspec[x][-1].scopenum) key=lambda x: self.arg2fixturedeflist[x][-1].scopenum)
def getfactorylist(self, argname, nodeid): def getfixturedeflist(self, argname, nodeid):
try: try:
factorydeflist = self.arg2facspec[argname] fixturedeflist = self.arg2fixturedeflist[argname]
except KeyError: except KeyError:
return None return None
else: else:
return list(self._matchfactories(factorydeflist, nodeid)) return list(self._matchfactories(fixturedeflist, nodeid))
def _matchfactories(self, factorydeflist, nodeid): def _matchfactories(self, fixturedeflist, nodeid):
for factorydef in factorydeflist: for fixturedef in fixturedeflist:
if nodeid.startswith(factorydef.baseid): if nodeid.startswith(fixturedef.baseid):
yield factorydef yield fixturedef
def _raiselookupfailed(self, argname, function, nodeid, getfactb=None): def _raiselookupfailed(self, argname, function, nodeid, getfixturetb=None):
available = [] available = []
for name, facdef in self.arg2facspec.items(): for name, fixturedef in self.arg2fixturedeflist.items():
faclist = list(self._matchfactories(facdef, nodeid)) faclist = list(self._matchfactories(fixturedef, 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,)
msg += "\n available funcargs: %s" %(", ".join(available),) msg += "\n available funcargs: %s" %(", ".join(available),)
msg += "\n use 'py.test --funcargs [testpath]' for help on them." msg += "\n use 'py.test --fixtures [testpath]' for help on them."
lines = getfactb and getfactb() or [] lines = getfixturetb and getfixturetb() or []
raise FuncargLookupError(function, msg, lines) raise FixtureLookupError(function, msg, lines)
def addargfinalizer(self, finalizer, argname): def addargfinalizer(self, finalizer, argname):
l = self._arg2finish.setdefault(argname, []) l = self._arg2finish.setdefault(argname, [])
@ -1456,11 +1459,11 @@ class FuncargManager:
except ValueError: except ValueError:
pass pass
class FactoryDef: class FixtureDef:
""" A container for a factory definition. """ """ A container for a factory definition. """
def __init__(self, funcargmanager, baseid, argname, func, scope, params, def __init__(self, fixturenanager, baseid, argname, func, scope, params,
unittest=False): unittest=False):
self.funcargmanager = funcargmanager self._fixturemanager = fixturenanager
self.baseid = baseid self.baseid = baseid
self.func = func self.func = func
self.argname = argname self.argname = argname
@ -1468,7 +1471,7 @@ class FactoryDef:
self.scopenum = scopes.index(scope or "function") self.scopenum = scopes.index(scope or "function")
self.params = params self.params = params
startindex = unittest and 1 or None startindex = unittest and 1 or None
self.funcargnames = getfuncargnames(func, startindex=startindex) self.fixturenames = getfuncargnames(func, startindex=startindex)
self.unittest = unittest self.unittest = unittest
self.active = False self.active = False
self._finalizer = [] self._finalizer = []
@ -1481,14 +1484,14 @@ class FactoryDef:
func = self._finalizer.pop() func = self._finalizer.pop()
func() func()
# check neccesity of next commented call # check neccesity of next commented call
self.funcargmanager.removefinalizer(self.finish) self._fixturemanager.removefinalizer(self.finish)
self.active = False self.active = False
#print "finished", self #print "finished", self
#del self.cached_result #del self.cached_result
def execute(self, request): def execute(self, request):
kwargs = {} kwargs = {}
for newname in self.funcargnames: for newname in self.fixturenames:
kwargs[newname] = request.getfuncargvalue(newname) kwargs[newname] = request.getfuncargvalue(newname)
if self.unittest: if self.unittest:
result = self.func(request.instance, **kwargs) result = self.func(request.instance, **kwargs)
@ -1499,7 +1502,7 @@ class FactoryDef:
return result return result
def __repr__(self): def __repr__(self):
return "<FactoryDef name=%r scope=%r>" % (self.argname, self.scope) return "<FixtureDef 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

View File

@ -21,7 +21,7 @@ def pytest_pycollect_makeitem(collector, name, obj):
class UnitTestCase(pytest.Class): class UnitTestCase(pytest.Class):
def collect(self): def collect(self):
self.session.funcargmanager._parsefactories(self.obj, self.nodeid, self.session._fixturemanager._parsefactories(self.obj, self.nodeid,
unittest=True) unittest=True)
loader = py.std.unittest.TestLoader() loader = py.std.unittest.TestLoader()
module = self.getparent(pytest.Module).obj module = self.getparent(pytest.Module).obj
@ -52,8 +52,8 @@ class UnitTestCase(pytest.Class):
class TestCaseFunction(pytest.Function): class TestCaseFunction(pytest.Function):
_excinfo = None _excinfo = None
def _getfixturenames(self): def _getfuncargnames(self):
return list(self.session.funcargmanager._autofixtures) return list(self.session._fixturemanager._autofixtures)
def setup(self): def setup(self):
self._testcase = self.parent.obj(self.name) self._testcase = self.parent.obj(self.name)
@ -65,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._fillfuncargs() self._request._fillfixtures()
def teardown(self): def teardown(self):
if hasattr(self._testcase, 'teardown_method'): if hasattr(self._testcase, 'teardown_method'):

View File

@ -25,7 +25,7 @@ Builtin resources / function arguments
You can ask for available builtin or project-custom You can ask for available builtin or project-custom
:ref:`function arguments <funcargs>` by typing:: :ref:`function arguments <funcargs>` by typing::
$ py.test --funcargs $ py.test --fixtures
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev2 platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev2
plugins: xdist, bugzilla, cache, oejskit, pep8, cov plugins: xdist, bugzilla, cache, oejskit, pep8, cov

View File

@ -15,7 +15,7 @@ def test_generative(param1, param2):
assert param1 * 2 < param2 assert param1 * 2 < param2
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
if 'param1' in metafunc.funcargnames: if 'param1' in metafunc.fixturenames:
metafunc.addcall(funcargs=dict(param1=3, param2=6)) metafunc.addcall(funcargs=dict(param1=3, param2=6))
class TestFailing(object): class TestFailing(object):

View File

@ -13,9 +13,9 @@ example: specifying and selecting acceptance tests
help="run (slow) acceptance tests") help="run (slow) acceptance tests")
def pytest_funcarg__accept(request): def pytest_funcarg__accept(request):
return AcceptFuncarg(request) return AcceptFixture(request)
class AcceptFuncarg: class AcceptFixture:
def __init__(self, request): def __init__(self, request):
if not request.config.option.acceptance: if not request.config.option.acceptance:
pytest.skip("specify -A to run acceptance tests") pytest.skip("specify -A to run acceptance tests")
@ -39,7 +39,7 @@ and the actual test function example:
If you run this test without specifying a command line option If you run this test without specifying a command line option
the test will get skipped with an appropriate message. Otherwise the test will get skipped with an appropriate message. Otherwise
you can start to add convenience and test support methods you can start to add convenience and test support methods
to your AcceptFuncarg and drive running of tools or to your AcceptFixture and drive running of tools or
applications and provide ways to do assertions about applications and provide ways to do assertions about
the output. the output.

View File

@ -84,7 +84,7 @@ Now we add a test configuration like this::
help="run all combinations") help="run all combinations")
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
if 'param1' in metafunc.funcargnames: if 'param1' in metafunc.fixturenames:
if metafunc.config.option.all: if metafunc.config.option.all:
end = 5 end = 5
else: else:
@ -213,7 +213,7 @@ creates a database object for the actual test invocations::
# content of conftest.py # content of conftest.py
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
if 'db' in metafunc.funcargnames: if 'db' in metafunc.fixturenames:
metafunc.parametrize("db", ['d1', 'd2'], indirect=True) metafunc.parametrize("db", ['d1', 'd2'], indirect=True)
class DB1: class DB1:

View File

@ -126,11 +126,11 @@ the ``MYARG`` function argument.
.. note:: .. note::
With pytest-2.3 you can use the :ref:`@pytest.fixture` decorator With pytest-2.3 you can use the :ref:`@pytest.fixture` decorator
to mark a function as a funcarg factory. to mark a function as a fixture function.
.. _`Convention over Configuration`: http://en.wikipedia.org/wiki/Convention_over_Configuration .. _`Convention over Configuration`: http://en.wikipedia.org/wiki/Convention_over_Configuration
Can I yield multiple values from a funcarg factory function? Can I yield multiple values from a fixture function function?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
There are two conceptual reasons why yielding from a factory function There are two conceptual reasons why yielding from a factory function

View File

@ -676,6 +676,6 @@ and provides methods to:
* to add finalizers/teardowns to be invoked when the last * to add finalizers/teardowns to be invoked when the last
test of the requesting test context executes test of the requesting test context executes
.. autoclass:: _pytest.python.FuncargRequest() .. autoclass:: _pytest.python.FixtureRequest()
:members: :members:

View File

@ -54,7 +54,7 @@ There are several limitations and difficulties with this approach:
4. there is no way how you can make use of funcarg factories 4. there is no way how you can make use of funcarg factories
in xUnit setup methods. in xUnit setup methods.
5. A non-parametrized funcarg factory cannot use a parametrized 5. A non-parametrized fixture function cannot use a parametrized
funcarg resource if it isn't stated in the test function signature. funcarg resource if it isn't stated in the test function signature.
All of these limitations are addressed with pytest-2.3 and its All of these limitations are addressed with pytest-2.3 and its

View File

@ -29,7 +29,7 @@ different variants of test resources to test with.
The basic mechanism for injecting objects is called the *funcarg The basic mechanism for injecting objects is called the *funcarg
mechanism* because objects are injected when a test or setup mechanism* because objects are injected when a test or setup
**function** states it as an **argument**. The injected argument **function** states it as an **argument**. The injected argument
is created by a call to a registered **funcarg factory** for each argument is created by a call to a registered **fixture function** for each argument
name. This mechanism is an example of `Dependency Injection`_ name. This mechanism is an example of `Dependency Injection`_
and helps to de-couple test code from the setup of required and helps to de-couple test code from the setup of required
objects: at test writing time you do not need to care for the details of objects: at test writing time you do not need to care for the details of
@ -38,7 +38,7 @@ shared on a per-class, module or session basis, or if your test function
is invoked multiple times with differently configured resource is invoked multiple times with differently configured resource
instances. instances.
Funcarg dependency injection allows to organise test resources Fixture dependency injection allows to organise test resources
in a modular explicit way so that test functions state their needs in a modular explicit way so that test functions state their needs
in their signature. pytest additionally offers powerful xunit-style in their signature. pytest additionally offers powerful xunit-style
:ref:`setup functions <setup functions>` for the cases where you need :ref:`setup functions <setup functions>` for the cases where you need
@ -144,7 +144,7 @@ with a list of available function arguments.
You can always issue:: You can always issue::
py.test --funcargs test_simplefactory.py py.test --fixtures test_simplefactory.py
to see available function arguments. to see available function arguments.
@ -289,7 +289,7 @@ that option::
help="run all combinations") help="run all combinations")
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
if 'param1' in metafunc.funcargnames: if 'param1' in metafunc.fixturenames:
if metafunc.config.option.all: if metafunc.config.option.all:
end = 5 end = 5
else: else:
@ -336,7 +336,7 @@ They help to inspect a testfunction and to generate tests
according to test configuration or values specified according to test configuration or values specified
in the class or module where a test function is defined: in the class or module where a test function is defined:
``metafunc.funcargnames``: set of required function arguments for given function ``metafunc.fixturenames``: set of required function arguments for given function
``metafunc.function``: underlying python test function ``metafunc.function``: underlying python test function
@ -346,6 +346,8 @@ in the class or module where a test function is defined:
``metafunc.config``: access to command line opts and general config ``metafunc.config``: access to command line opts and general config
``metafunc.funcargnames``: alias for ``fixturenames``, for pre-2.3 compatibility
.. automethod:: Metafunc.parametrize .. automethod:: Metafunc.parametrize
.. automethod:: Metafunc.addcall(funcargs=None,id=_notexists,param=_notexists) .. automethod:: Metafunc.addcall(funcargs=None,id=_notexists,param=_notexists)
@ -360,7 +362,7 @@ in the class or module where a test function is defined:
Compatibility notes Compatibility notes
============================================================ ============================================================
**Funcargs** were originally introduced to pytest-2.0. In pytest-2.3 **Fixtures** were originally introduced to pytest-2.0. In pytest-2.3
the mechanism was extended and refined: the mechanism was extended and refined:
* previously funcarg factories were specified with a special * previously funcarg factories were specified with a special
@ -376,14 +378,14 @@ the mechanism was extended and refined:
* if you used parametrization and funcarg factories which made use of * if you used parametrization and funcarg factories which made use of
``request.cached_setup()`` it is recommeneded to invest a few minutes ``request.cached_setup()`` it is recommeneded to invest a few minutes
and simplify your funcarg factory code to use the `@pytest.fixture`_ and simplify your fixture function code to use the `@pytest.fixture`_
decorator instead. This will also allow to take advantage of decorator instead. This will also allow to take advantage of
the `automatic per-resource grouping`_ of tests. the `automatic per-resource grouping`_ of tests.
.. note:: .. note::
Throughout the pytest documents the ``pytest_funcarg__NAME`` way of Throughout the pytest documents the ``pytest_funcarg__NAME`` way of
defining a funcarg factory is often termed "old-style". Their defining a fixture function is often termed "old-style". Their
use remains fully supported and existing code using it should run use remains fully supported and existing code using it should run
unmodified. unmodified.

View File

@ -186,7 +186,7 @@ was created. More info at :ref:`tmpdir handling`.
You can find out what kind of builtin :ref:`funcargs` exist by typing:: You can find out what kind of builtin :ref:`funcargs` exist by typing::
py.test --funcargs # shows builtin and custom function arguments py.test --fixtures # shows builtin and custom function arguments
Where to go next Where to go next
------------------------------------- -------------------------------------

View File

@ -24,7 +24,7 @@ command line options
traceback print mode (long/short/line/no). traceback print mode (long/short/line/no).
``--fulltrace`` ``--fulltrace``
don't cut any tracebacks (default is to cut). don't cut any tracebacks (default is to cut).
``--funcargs`` ``--fixtures``
show available function arguments, sorted by plugin show available function arguments, sorted by plugin
Start improving this plugin in 30 seconds Start improving this plugin in 30 seconds

View File

@ -26,7 +26,7 @@ Getting help on version, option names, environment variables
:: ::
py.test --version # shows where pytest was imported from py.test --version # shows where pytest was imported from
py.test --funcargs # show available builtin function arguments py.test --fixtures # show available builtin function arguments
py.test -h | --help # show help on command line and config file options py.test -h | --help # show help on command line and config file options

View File

@ -47,7 +47,7 @@ Python インタープリターの対話モードから次のように入力す
次のように入力して、利用できる組み込みまたはプロジェクトカスタムの :ref:`関数の引数 <funcargs>` を確認できます。 次のように入力して、利用できる組み込みまたはプロジェクトカスタムの :ref:`関数の引数 <funcargs>` を確認できます。
| $ py.test --funcargs | $ py.test --fixtures
| ====================== test session starts ======================= | ====================== test session starts =======================
| platform linux2 -- Python 2.7.1 -- pytest-2.2.4 | platform linux2 -- Python 2.7.1 -- pytest-2.2.4
| collected 0 items | collected 0 items
@ -98,7 +98,7 @@ Python インタープリターの対話モードから次のように入力す
| ======================== in 0.00 seconds ======================== | ======================== in 0.00 seconds ========================
.. ..
$ py.test --funcargs $ py.test --fixtures
=========================== test session starts ============================ =========================== test session starts ============================
platform linux2 -- Python 2.7.1 -- pytest-2.2.4 platform linux2 -- Python 2.7.1 -- pytest-2.2.4
collected 0 items collected 0 items

View File

@ -15,7 +15,7 @@ def test_generative(param1, param2):
assert param1 * 2 < param2 assert param1 * 2 < param2
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
if 'param1' in metafunc.funcargnames: if 'param1' in metafunc.fixturenames:
metafunc.addcall(funcargs=dict(param1=3, param2=6)) metafunc.addcall(funcargs=dict(param1=3, param2=6))
class TestFailing(object): class TestFailing(object):

View File

@ -13,9 +13,9 @@ example: specifying and selecting acceptance tests
help="run (slow) acceptance tests") help="run (slow) acceptance tests")
def pytest_funcarg__accept(request): def pytest_funcarg__accept(request):
return AcceptFuncarg(request) return AcceptFixture(request)
class AcceptFuncarg: class AcceptFixture:
def __init__(self, request): def __init__(self, request):
if not request.config.option.acceptance: if not request.config.option.acceptance:
pytest.skip("specify -A to run acceptance tests") pytest.skip("specify -A to run acceptance tests")
@ -39,7 +39,7 @@ and the actual test function example:
If you run this test without specifying a command line option If you run this test without specifying a command line option
the test will get skipped with an appropriate message. Otherwise the test will get skipped with an appropriate message. Otherwise
you can start to add convenience and test support methods you can start to add convenience and test support methods
to your AcceptFuncarg and drive running of tools or to your AcceptFixture and drive running of tools or
applications and provide ways to do assertions about applications and provide ways to do assertions about
the output. the output.

View File

@ -11,7 +11,7 @@ def pytest_generate_tests(metafunc):
# over the python interpreters of our list above - the actual # over the python interpreters of our list above - the actual
# setup and lookup of interpreters in the python1/python2 factories # setup and lookup of interpreters in the python1/python2 factories
# respectively. # respectively.
for arg in metafunc.funcargnames: for arg in metafunc.fixturenames:
if arg in ("python1", "python2"): if arg in ("python1", "python2"):
metafunc.parametrize(arg, pythonlist, indirect=True) metafunc.parametrize(arg, pythonlist, indirect=True)

View File

@ -117,7 +117,7 @@ py.test は、簡単にパラメーターをテスト関数へ渡せます。パ
help="run all combinations") help="run all combinations")
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
if 'param1' in metafunc.funcargnames: if 'param1' in metafunc.fixturenames:
if metafunc.config.option.all: if metafunc.config.option.all:
end = 5 end = 5
else: else:
@ -266,7 +266,7 @@ Robert Collins による標準ライブラリの unittest フレームワーク
# conftest.py の内容 # conftest.py の内容
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
if 'db' in metafunc.funcargnames: if 'db' in metafunc.fixturenames:
metafunc.parametrize("db", ['d1', 'd2'], indirect=True) metafunc.parametrize("db", ['d1', 'd2'], indirect=True)
class DB1: class DB1:

View File

@ -153,7 +153,7 @@ funcarg ファクトリー関数から複数の値を yield できますか?
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.. ..
Can I yield multiple values from a funcarg factory function? Can I yield multiple values from a fixture function function?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.. ..

View File

@ -157,7 +157,7 @@ py.test には :ref:`builtinfuncargs` が付属していて、そのサンプル
いつでも次のようにして:: いつでも次のようにして::
py.test --funcargs test_simplefactory.py py.test --fixtures test_simplefactory.py
.. ..
to see available function arguments (which you can also to see available function arguments (which you can also
@ -171,7 +171,7 @@ py.test には :ref:`builtinfuncargs` が付属していて、そのサンプル
.. _`xUnit style`: xunit_setup.html .. _`xUnit style`: xunit_setup.html
.. _`funcarg factory`: .. _`fixture function`:
.. _factory: .. _factory:
funcarg **request** オブジェクト funcarg **request** オブジェクト
@ -182,24 +182,24 @@ funcarg **request** オブジェクト
============================================= =============================================
.. ..
Each funcarg factory receives a **request** object tied to a specific test Each fixture function receives a **request** object tied to a specific test
function call. A request object is passed to a funcarg factory and provides function call. A request object is passed to a fixture function and provides
access to test configuration and context: access to test configuration and context:
funcarg ファクトリー関数は、特別なテスト関数呼び出しに関連付けられた **request** オブジェクトを受け取ります。request オブジェクトは funcarg ファクトリーへ渡されて、テスト設定とコンテキストへのアクセスを提供します: funcarg ファクトリー関数は、特別なテスト関数呼び出しに関連付けられた **request** オブジェクトを受け取ります。request オブジェクトは funcarg ファクトリーへ渡されて、テスト設定とコンテキストへのアクセスを提供します:
.. autoclass:: _pytest.python.FuncargRequest() .. autoclass:: _pytest.python.FixtureRequest()
:members: function,cls,module,keywords,config :members: function,cls,module,keywords,config
.. _`useful caching and finalization helpers`: .. _`useful caching and finalization helpers`:
.. automethod:: FuncargRequest.addfinalizer .. automethod:: FixtureRequest.addfinalizer
.. automethod:: FuncargRequest.cached_setup .. automethod:: FixtureRequest.cached_setup
.. automethod:: FuncargRequest.applymarker .. automethod:: FixtureRequest.applymarker
.. automethod:: FuncargRequest.getfuncargvalue .. automethod:: FixtureRequest.getfuncargvalue
.. _`test generators`: .. _`test generators`:
@ -236,7 +236,7 @@ funcarg ファクトリー関数は、特別なテスト関数呼び出しに関
# test_example.py の内容 # test_example.py の内容
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
if "numiter" in metafunc.funcargnames: if "numiter" in metafunc.fixturenames:
metafunc.parametrize("numiter", range(10)) metafunc.parametrize("numiter", range(10))
def test_func(numiter): def test_func(numiter):
@ -329,9 +329,9 @@ funcarg ファクトリー関数は、特別なテスト関数呼び出しに関
metafunc オブジェクトは ``pytest_generate_tests`` フックへ渡されます。これはテスト関数を検査したり、テスト設定またはテスト関数が定義されているクラスやモジュールで指定された値を取るテストを生成するのに役立ちます: metafunc オブジェクトは ``pytest_generate_tests`` フックへ渡されます。これはテスト関数を検査したり、テスト設定またはテスト関数が定義されているクラスやモジュールで指定された値を取るテストを生成するのに役立ちます:
.. ..
``metafunc.funcargnames``: set of required function arguments for given function ``metafunc.fixturenames``: set of required function arguments for given function
``metafunc.funcargnames``: テスト関数へ渡される引数セット ``metafunc.fixturenames``: テスト関数へ渡される引数セット
.. ..
``metafunc.function``: underlying python test function ``metafunc.function``: underlying python test function

View File

@ -265,7 +265,7 @@ py.test は :ref:`標準的なテスト探索ルール <test discovery>` に従
組み込みの :ref:`funcargs` を把握するには、次のコマンドを実行します:: 組み込みの :ref:`funcargs` を把握するには、次のコマンドを実行します::
py.test --funcargs # 組み込み/カスタムの関数の引数を表示する py.test --fixtures # 組み込み/カスタムの関数の引数を表示する
.. ..
Where to go next Where to go next

View File

@ -24,7 +24,7 @@ command line options
traceback print mode (long/short/line/no). traceback print mode (long/short/line/no).
``--fulltrace`` ``--fulltrace``
don't cut any tracebacks (default is to cut). don't cut any tracebacks (default is to cut).
``--funcargs`` ``--fixtures``
show available function arguments, sorted by plugin show available function arguments, sorted by plugin
Start improving this plugin in 30 seconds Start improving this plugin in 30 seconds

View File

@ -43,7 +43,7 @@ Python 2.5 か、それ以上のバージョンを使っているなら、コマ
:: ::
py.test --version # pytest がインポートされた場所を表示 py.test --version # pytest がインポートされた場所を表示
py.test --funcargs # 利用できる組み込みの関数引数を表示 py.test --fixtures # 利用できる組み込みの関数引数を表示
py.test -h | --help # コマンドラインと設定ファイルオプションのヘルプを表示 py.test -h | --help # コマンドラインと設定ファイルオプションのヘルプを表示
.. ..

View File

@ -64,7 +64,7 @@ def pytest_generate_tests(metafunc):
for name, l in multi.kwargs.items(): for name, l in multi.kwargs.items():
for val in l: for val in l:
metafunc.addcall(funcargs={name: val}) metafunc.addcall(funcargs={name: val})
elif 'anypython' in metafunc.funcargnames: elif 'anypython' in metafunc.fixturenames:
for name in ('python2.4', 'python2.5', 'python2.6', for name in ('python2.4', 'python2.5', 'python2.6',
'python2.7', 'python3.1', 'pypy', 'jython'): 'python2.7', 'python3.1', 'pypy', 'jython'):
metafunc.addcall(id=name, param=name) metafunc.addcall(id=name, param=name)

View File

@ -363,7 +363,7 @@ class TestLoggingInteraction:
assert 'operation on closed file' not in result.stderr.str() assert 'operation on closed file' not in result.stderr.str()
class TestCaptureFuncarg: class TestCaptureFixture:
def test_std_functional(self, testdir): def test_std_functional(self, testdir):
reprec = testdir.inline_runsource(""" reprec = testdir.inline_runsource("""
def test_hello(capsys): def test_hello(capsys):

View File

@ -2,7 +2,7 @@ import py, pytest
from _pytest.config import Conftest from _pytest.config import Conftest
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
if "basedir" in metafunc.funcargnames: if "basedir" in metafunc.fixturenames:
metafunc.addcall(param="global") metafunc.addcall(param="global")
metafunc.addcall(param="inpackage") metafunc.addcall(param="inpackage")

View File

@ -22,7 +22,7 @@ def test_help(testdir):
*setup.cfg* *setup.cfg*
*minversion* *minversion*
*to see*markers*py.test --markers* *to see*markers*py.test --markers*
*to see*funcargs*py.test --funcargs* *to see*fixtures*py.test --fixtures*
""") """)
def test_collectattr(): def test_collectattr():

View File

@ -1,6 +1,6 @@
import pytest, py, sys import pytest, py, sys
from _pytest import python as funcargs from _pytest import python as funcargs
from _pytest.python import FuncargLookupError from _pytest.python import FixtureLookupError
class TestModule: class TestModule:
def test_failing_import(self, testdir): def test_failing_import(self, testdir):
@ -276,10 +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 from _pytest.python import FixtureManager
config = testdir.parseconfigure() config = testdir.parseconfigure()
session = testdir.Session(config) session = testdir.Session(config)
session.funcargmanager = FuncargManager(session) session._fixturemanager = FixtureManager(session)
def func1(): def func1():
pass pass
def func2(): def func2():
@ -542,10 +542,10 @@ def test_getfuncargnames():
pass pass
assert funcargs.getfuncargnames(A) == ["x"] assert funcargs.getfuncargnames(A) == ["x"]
class TestFillFuncArgs: class TestFillFixtures:
def test_fillfuncargs_exposed(self): def test_fillfuncargs_exposed(self):
# used by oejskit # used by oejskit, kept for compatibility
assert pytest._fillfuncargs == funcargs.fillfuncargs assert pytest._fillfuncargs == funcargs.fillfixtures
def test_funcarg_lookupfails(self, testdir): def test_funcarg_lookupfails(self, testdir):
testdir.makepyfile(""" testdir.makepyfile("""
@ -572,7 +572,7 @@ class TestFillFuncArgs:
def test_func(some, other): def test_func(some, other):
pass pass
""") """)
funcargs.fillfuncargs(item) funcargs.fillfixtures(item)
assert len(item.funcargs) == 2 assert len(item.funcargs) == 2
assert item.funcargs['some'] == "test_func" assert item.funcargs['some'] == "test_func"
assert item.funcargs['other'] == 42 assert item.funcargs['other'] == 42
@ -611,7 +611,7 @@ class TestRequest:
def pytest_funcarg__something(request): pass def pytest_funcarg__something(request): pass
def test_func(something): pass def test_func(something): pass
""") """)
req = funcargs.FuncargRequest(item) req = funcargs.FixtureRequest(item)
assert req.function == item.obj assert req.function == item.obj
assert req.keywords == item.keywords assert req.keywords == item.keywords
assert hasattr(req.module, 'test_func') assert hasattr(req.module, 'test_func')
@ -632,7 +632,7 @@ class TestRequest:
assert req.cls.__name__ == "TestB" assert req.cls.__name__ == "TestB"
assert req.instance.__class__ == req.cls assert req.instance.__class__ == req.cls
def XXXtest_request_contains_funcarg_name2factory(self, testdir): def XXXtest_request_contains_funcarg_arg2fixturedeflist(self, testdir):
modcol = testdir.getmodulecol(""" modcol = testdir.getmodulecol("""
def pytest_funcarg__something(request): def pytest_funcarg__something(request):
pass pass
@ -642,9 +642,9 @@ class TestRequest:
""") """)
item1, = testdir.genitems([modcol]) item1, = testdir.genitems([modcol])
assert item1.name == "test_method" assert item1.name == "test_method"
name2factory = funcargs.FuncargRequest(item1)._name2factory arg2fixturedeflist = funcargs.FixtureRequest(item1)._arg2fixturedeflist
assert len(name2factory) == 1 assert len(arg2fixturedeflist) == 1
assert name2factory[0].__name__ == "pytest_funcarg__something" assert arg2fixturedeflist[0].__name__ == "pytest_funcarg__something"
def test_getfuncargvalue_recursive(self, testdir): def test_getfuncargvalue_recursive(self, testdir):
testdir.makeconftest(""" testdir.makeconftest("""
@ -669,7 +669,7 @@ class TestRequest:
def test_func(something): pass def test_func(something): pass
""") """)
req = item._request req = item._request
pytest.raises(FuncargLookupError, req.getfuncargvalue, "notexists") pytest.raises(FixtureLookupError, req.getfuncargvalue, "notexists")
val = req.getfuncargvalue("something") val = req.getfuncargvalue("something")
assert val == 1 assert val == 1
val = req.getfuncargvalue("something") val = req.getfuncargvalue("something")
@ -717,7 +717,7 @@ class TestRequest:
def test_request_getmodulepath(self, testdir): def test_request_getmodulepath(self, testdir):
modcol = testdir.getmodulecol("def test_somefunc(): pass") modcol = testdir.getmodulecol("def test_somefunc(): pass")
item, = testdir.genitems([modcol]) item, = testdir.genitems([modcol])
req = funcargs.FuncargRequest(item) req = funcargs.FixtureRequest(item)
assert req.fspath == modcol.fspath assert req.fspath == modcol.fspath
class TestMarking: class TestMarking:
@ -731,7 +731,7 @@ class TestMarking:
def test_func2(self, something): def test_func2(self, something):
pass pass
""") """)
req1 = funcargs.FuncargRequest(item1) req1 = funcargs.FixtureRequest(item1)
assert 'xfail' not in item1.keywords assert 'xfail' not in item1.keywords
req1.applymarker(pytest.mark.xfail) req1.applymarker(pytest.mark.xfail)
assert 'xfail' in item1.keywords assert 'xfail' in item1.keywords
@ -814,7 +814,7 @@ class TestRequestCachedSetup:
def test_request_cachedsetup_extrakey(self, testdir): def test_request_cachedsetup_extrakey(self, testdir):
item1 = testdir.getitem("def test_func(): pass") item1 = testdir.getitem("def test_func(): pass")
req1 = funcargs.FuncargRequest(item1) req1 = funcargs.FixtureRequest(item1)
l = ["hello", "world"] l = ["hello", "world"]
def setup(): def setup():
return l.pop() return l.pop()
@ -829,7 +829,7 @@ class TestRequestCachedSetup:
def test_request_cachedsetup_cache_deletion(self, testdir): def test_request_cachedsetup_cache_deletion(self, testdir):
item1 = testdir.getitem("def test_func(): pass") item1 = testdir.getitem("def test_func(): pass")
req1 = funcargs.FuncargRequest(item1) req1 = funcargs.FixtureRequest(item1)
l = [] l = []
def setup(): def setup():
l.append("setup") l.append("setup")
@ -906,14 +906,14 @@ class TestMetafunc:
def test_no_funcargs(self, testdir): def test_no_funcargs(self, testdir):
def function(): pass def function(): pass
metafunc = funcargs.Metafunc(function) metafunc = funcargs.Metafunc(function)
assert not metafunc.funcargnames assert not metafunc.fixturenames
repr(metafunc._calls) repr(metafunc._calls)
def test_function_basic(self): def test_function_basic(self):
def func(arg1, arg2="qwe"): pass def func(arg1, arg2="qwe"): pass
metafunc = funcargs.Metafunc(func) metafunc = funcargs.Metafunc(func)
assert len(metafunc.funcargnames) == 1 assert len(metafunc.fixturenames) == 1
assert 'arg1' in metafunc.funcargnames assert 'arg1' in metafunc.fixturenames
assert metafunc.function is func assert metafunc.function is func
assert metafunc.cls is None assert metafunc.cls is None
@ -1032,7 +1032,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 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):
@ -1170,7 +1170,7 @@ class TestMetafuncFunctional:
def test_addcall_with_two_funcargs_generators(self, testdir): def test_addcall_with_two_funcargs_generators(self, testdir):
testdir.makeconftest(""" testdir.makeconftest("""
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
assert "arg1" in metafunc.funcargnames assert "arg1" in metafunc.fixturenames
metafunc.addcall(funcargs=dict(arg1=1, arg2=2)) metafunc.addcall(funcargs=dict(arg1=1, arg2=2))
""") """)
p = testdir.makepyfile(""" p = testdir.makepyfile("""
@ -1213,7 +1213,7 @@ class TestMetafuncFunctional:
def test_noself_in_method(self, testdir): def test_noself_in_method(self, testdir):
p = testdir.makepyfile(""" p = testdir.makepyfile("""
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
assert 'xyz' not in metafunc.funcargnames assert 'xyz' not in metafunc.fixturenames
class TestHello: class TestHello:
def test_hello(xyz): def test_hello(xyz):
@ -1228,7 +1228,7 @@ class TestMetafuncFunctional:
def test_generate_plugin_and_module(self, testdir): def test_generate_plugin_and_module(self, testdir):
testdir.makeconftest(""" testdir.makeconftest("""
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
assert "arg1" in metafunc.funcargnames assert "arg1" in metafunc.fixturenames
metafunc.addcall(id="world", param=(2,100)) metafunc.addcall(id="world", param=(2,100))
""") """)
p = testdir.makepyfile(""" p = testdir.makepyfile("""
@ -1342,7 +1342,7 @@ class TestMetafuncFunctional:
def test_parametrize_on_setup_arg(self, testdir): def test_parametrize_on_setup_arg(self, testdir):
p = testdir.makepyfile(""" p = testdir.makepyfile("""
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
assert "arg1" in metafunc.funcargnames assert "arg1" in metafunc.fixturenames
metafunc.parametrize("arg1", [1], indirect=True) metafunc.parametrize("arg1", [1], indirect=True)
def pytest_funcarg__arg1(request): def pytest_funcarg__arg1(request):
@ -1403,7 +1403,7 @@ def test_funcarg_non_pycollectobj(testdir): # rough jstests usage
clscol = rep.result[0] clscol = rep.result[0]
clscol.obj = lambda arg1: None clscol.obj = lambda arg1: None
clscol.funcargs = {} clscol.funcargs = {}
funcargs.fillfuncargs(clscol) funcargs.fillfixtures(clscol)
assert clscol.funcargs['arg1'] == 42 assert clscol.funcargs['arg1'] == 42
@ -1488,7 +1488,7 @@ class TestReportInfo:
""" """
def test_show_funcarg(testdir): def test_show_funcarg(testdir):
result = testdir.runpytest("--funcargs") result = testdir.runpytest("--fixtures")
result.stdout.fnmatch_lines([ result.stdout.fnmatch_lines([
"*tmpdir*", "*tmpdir*",
"*temporary directory*", "*temporary directory*",
@ -1669,7 +1669,7 @@ def test_issue117_sessionscopeteardown(testdir):
]) ])
class TestFuncargFactory: class TestFixtureFactory:
def test_receives_funcargs(self, testdir): def test_receives_funcargs(self, testdir):
testdir.makepyfile(""" testdir.makepyfile("""
import pytest import pytest
@ -1809,7 +1809,7 @@ class TestResourceIntegrationFunctional:
"*test_function*advanced*FAILED", "*test_function*advanced*FAILED",
]) ])
class TestFuncargManager: class TestFixtureManager:
def pytest_funcarg__testdir(self, request): def pytest_funcarg__testdir(self, request):
testdir = request.getfuncargvalue("testdir") testdir = request.getfuncargvalue("testdir")
testdir.makeconftest(""" testdir.makeconftest("""
@ -1817,7 +1817,7 @@ class TestFuncargManager:
return "conftest" return "conftest"
def pytest_funcarg__fm(request): def pytest_funcarg__fm(request):
return request.funcargmanager return request._fixturemanager
def pytest_funcarg__item(request): def pytest_funcarg__item(request):
return request._pyfuncitem return request._pyfuncitem
@ -1828,7 +1828,7 @@ class TestFuncargManager:
testdir.makepyfile(""" testdir.makepyfile("""
def test_hello(item, fm): def test_hello(item, fm):
for name in ("fm", "hello", "item"): for name in ("fm", "hello", "item"):
faclist = fm.getfactorylist(name, item.nodeid) faclist = fm.getfixturedeflist(name, item.nodeid)
assert len(faclist) == 1 assert len(faclist) == 1
fac = faclist[0] fac = faclist[0]
assert fac.func.__name__ == "pytest_funcarg__" + name assert fac.func.__name__ == "pytest_funcarg__" + name
@ -1844,7 +1844,7 @@ class TestFuncargManager:
def pytest_funcarg__hello(self, request): def pytest_funcarg__hello(self, request):
return "class" return "class"
def test_hello(self, item, fm): def test_hello(self, item, fm):
faclist = fm.getfactorylist("hello", item.nodeid) faclist = fm.getfixturedeflist("hello", item.nodeid)
print (faclist) print (faclist)
assert len(faclist) == 3 assert len(faclist) == 3
assert faclist[0].func(item._request) == "conftest" assert faclist[0].func(item._request) == "conftest"
@ -1870,7 +1870,7 @@ class TestSetupDiscovery:
pass pass
def pytest_funcarg__fm(request): def pytest_funcarg__fm(request):
return request.funcargmanager return request._fixturemanager
def pytest_funcarg__item(request): def pytest_funcarg__item(request):
return request._pyfuncitem return request._pyfuncitem
@ -1919,11 +1919,11 @@ class TestSetupDiscovery:
pass pass
def test_func1(request): def test_func1(request):
assert "db" not in request.funcargnames assert "db" not in request.fixturenames
@pytest.mark.needsdb @pytest.mark.needsdb
def test_func2(request): def test_func2(request):
assert "db" in request.funcargnames assert "db" in request.fixturenames
""") """)
reprec = testdir.inline_run("-s") reprec = testdir.inline_run("-s")
reprec.assertoutcome(passed=2) reprec.assertoutcome(passed=2)
@ -2105,7 +2105,7 @@ class TestSetupManagement:
reprec.assertoutcome(passed=5) reprec.assertoutcome(passed=5)
class TestFuncargMarker: class TestFixtureMarker:
def test_parametrize(self, testdir): def test_parametrize(self, testdir):
testdir.makepyfile(""" testdir.makepyfile("""
import pytest import pytest
@ -2686,7 +2686,7 @@ def test_setup_funcarg_order(testdir):
reprec.assertoutcome(passed=1) reprec.assertoutcome(passed=1)
def test_request_funcargnames(testdir): def test_request_fixturenames(testdir):
testdir.makepyfile(""" testdir.makepyfile("""
import pytest import pytest
@pytest.fixture() @pytest.fixture()
@ -2699,8 +2699,23 @@ def test_request_funcargnames(testdir):
def sarg(tmpdir): def sarg(tmpdir):
pass pass
def test_function(request, farg): def test_function(request, farg):
assert set(request.funcargnames) == \ assert set(request.fixturenames) == \
set(["tmpdir", "sarg", "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)
def test_funcargnames_compatattr(testdir):
testdir.makepyfile("""
def pytest_generate_tests(metafunc):
assert metafunc.funcargnames == metafunc.fixturenames
def pytest_funcarg__fn(request):
assert request._pyfuncitem.funcargnames == \
request._pyfuncitem.fixturenames
return request.funcargnames, request.fixturenames
def test_hello(fn):
assert fn[0] == fn[1]
""")
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)

View File

@ -26,7 +26,7 @@ class Option:
return l return l
def pytest_generate_tests(metafunc): def pytest_generate_tests(metafunc):
if "option" in metafunc.funcargnames: if "option" in metafunc.fixturenames:
metafunc.addcall(id="default", metafunc.addcall(id="default",
funcargs={'option': Option(verbose=False)}) funcargs={'option': Option(verbose=False)})
metafunc.addcall(id="verbose", metafunc.addcall(id="verbose",