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:
parent
8282efbb40
commit
bb07ba7807
|
@ -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
|
||||
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
|
||||
item.getresource(X) for all X in the funcargs of a function.
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ def pytest_funcarg__capsys(request):
|
|||
"""
|
||||
if "capfd" in request._funcargs:
|
||||
raise request.raiseerror(error_capsysfderror)
|
||||
return CaptureFuncarg(py.io.StdCapture)
|
||||
return CaptureFixture(py.io.StdCapture)
|
||||
|
||||
def pytest_funcarg__capfd(request):
|
||||
"""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)
|
||||
if not hasattr(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):
|
||||
self.capture = captureclass(now=False)
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ def showhelp(config):
|
|||
tw.line() ; tw.line()
|
||||
#tw.sep("=")
|
||||
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
|
||||
|
||||
tw.line("conftest.py options:")
|
||||
|
|
|
@ -308,8 +308,8 @@ class Node(object):
|
|||
pass
|
||||
|
||||
def _repr_failure_py(self, excinfo, style=None):
|
||||
fm = self.session.funcargmanager
|
||||
if excinfo.errisinstance(fm.FuncargLookupError):
|
||||
fm = self.session._fixturemanager
|
||||
if excinfo.errisinstance(fm.FixtureLookupError):
|
||||
function = excinfo.value.function
|
||||
factblines = excinfo.value.factblines
|
||||
if function is not None:
|
||||
|
@ -317,7 +317,7 @@ class Node(object):
|
|||
lines, _ = inspect.getsourcelines(function)
|
||||
for i, line in enumerate(lines):
|
||||
if line.strip().startswith('def'):
|
||||
return fm.FuncargLookupErrorRepr(fspath,
|
||||
return fm.FixtureLookupErrorRepr(fspath,
|
||||
lineno, lines[:i+1],
|
||||
str(excinfo.value.msg), factblines)
|
||||
if self.config.option.fulltrace:
|
||||
|
|
|
@ -44,18 +44,7 @@ defaultfuncargprefixmarker = fixture()
|
|||
|
||||
# XXX remove in favour of fixture(autoactive=True)
|
||||
def setup(scope="function"):
|
||||
""" return a decorator to mark a function as providing a fixture for
|
||||
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".
|
||||
"""
|
||||
""" alias for fixture(scope, autoactive=True) """
|
||||
return FixtureFunctionMarker(scope, params=None, autoactive=True)
|
||||
|
||||
def cached_property(f):
|
||||
|
@ -85,9 +74,9 @@ def pyobj_property(name):
|
|||
|
||||
def pytest_addoption(parser):
|
||||
group = parser.getgroup("general")
|
||||
group.addoption('--funcargs',
|
||||
action="store_true", dest="showfuncargs", default=False,
|
||||
help="show available function arguments, sorted by plugin")
|
||||
group.addoption('--fixtures', '--fixtures',
|
||||
action="store_true", dest="showfixtures", default=False,
|
||||
help="show available fixtures, sorted by plugin appearance")
|
||||
parser.addini("python_files", type="args",
|
||||
default=('test_*.py', '*_test.py'),
|
||||
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")
|
||||
|
||||
def pytest_cmdline_main(config):
|
||||
if config.option.showfuncargs:
|
||||
showfuncargs(config)
|
||||
if config.option.showfixtures:
|
||||
showfixtures(config)
|
||||
return 0
|
||||
|
||||
|
||||
|
@ -119,7 +108,7 @@ def pytest_configure(config):
|
|||
)
|
||||
|
||||
def pytest_sessionstart(session):
|
||||
session.funcargmanager = FuncargManager(session)
|
||||
session._fixturemanager = FixtureManager(session)
|
||||
|
||||
@pytest.mark.trylast
|
||||
def pytest_namespace():
|
||||
|
@ -131,10 +120,11 @@ def pytest_namespace():
|
|||
'collect': {
|
||||
'Module': Module, 'Class': Class, 'Instance': Instance,
|
||||
'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."""
|
||||
return request.config
|
||||
|
||||
|
@ -146,12 +136,12 @@ def pytest_pyfunc_call(__multicall__, pyfuncitem):
|
|||
testfunction(*pyfuncitem._args)
|
||||
else:
|
||||
try:
|
||||
funcargnames = pyfuncitem.funcargnames
|
||||
fixturenames = pyfuncitem.fixturenames
|
||||
except AttributeError:
|
||||
funcargs = pyfuncitem.funcargs
|
||||
else:
|
||||
funcargs = {}
|
||||
for name in funcargnames:
|
||||
for name in fixturenames:
|
||||
funcargs[name] = pyfuncitem.funcargs[name]
|
||||
testfunction(**funcargs)
|
||||
|
||||
|
@ -352,7 +342,7 @@ class Module(pytest.File, PyCollector):
|
|||
return self._memoizedcall('_obj', self._importtestmodule)
|
||||
|
||||
def collect(self):
|
||||
self.session.funcargmanager._parsefactories(self.obj, self.nodeid)
|
||||
self.session._fixturemanager._parsefactories(self.obj, self.nodeid)
|
||||
return super(Module, self).collect()
|
||||
|
||||
def _importtestmodule(self):
|
||||
|
@ -425,7 +415,7 @@ class Instance(PyCollector):
|
|||
return obj
|
||||
|
||||
def collect(self):
|
||||
self.session.funcargmanager._parsefactories(self.obj, self.nodeid)
|
||||
self.session._fixturemanager._parsefactories(self.obj, self.nodeid)
|
||||
return super(Instance, self).collect()
|
||||
|
||||
def newinstance(self):
|
||||
|
@ -534,14 +524,14 @@ def hasinit(obj):
|
|||
|
||||
|
||||
|
||||
def fillfuncargs(function):
|
||||
def fillfixtures(function):
|
||||
""" fill missing funcargs for a test function. """
|
||||
if getattr(function, "_args", None) is None: # not a yielded function
|
||||
try:
|
||||
request = function._request
|
||||
except AttributeError:
|
||||
request = function._request = FuncargRequest(function)
|
||||
request._fillfuncargs()
|
||||
request = function._request = FixtureRequest(function)
|
||||
request._fillfixtures()
|
||||
|
||||
_notexists = object()
|
||||
|
||||
|
@ -605,21 +595,30 @@ class CallSpec2(object):
|
|||
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,
|
||||
parentnode=None):
|
||||
self.config = config
|
||||
self.module = module
|
||||
self.function = function
|
||||
self.parentnode = parentnode
|
||||
self.parentid = getattr(parentnode, "nodeid", "")
|
||||
self._parentid = getattr(parentnode, "nodeid", "")
|
||||
argnames = getfuncargnames(function, startindex=int(cls is not None))
|
||||
if parentnode is not None:
|
||||
fm = parentnode.session.funcargmanager
|
||||
self.funcargnames, self._arg2facdeflist = fm.getallfuncargnames(
|
||||
fm = parentnode.session._fixturemanager
|
||||
self.fixturenames, self._arg2fixturedeflist = fm.getfixtureclosure(
|
||||
argnames, parentnode)
|
||||
else:
|
||||
self.funcargnames = argnames
|
||||
self.fixturenames = argnames
|
||||
self.cls = cls
|
||||
self.module = module
|
||||
self._calls = []
|
||||
|
@ -631,7 +630,7 @@ class Metafunc:
|
|||
""" Add new invocations to the underlying test function using the list
|
||||
of argvalues for the given argnames. Parametrization is performed
|
||||
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.
|
||||
|
||||
:arg argnames: an argument name or a list of argument names
|
||||
|
@ -640,7 +639,7 @@ class Metafunc:
|
|||
values for the list of argument names.
|
||||
|
||||
: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
|
||||
a test rather than at collection time.
|
||||
|
||||
|
@ -657,7 +656,7 @@ class Metafunc:
|
|||
if not indirect:
|
||||
#XXX should we also check for the opposite case?
|
||||
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))
|
||||
valtype = indirect and "params" or "funcargs"
|
||||
if not ids:
|
||||
|
@ -686,13 +685,13 @@ class Metafunc:
|
|||
:arg id: used for reporting and identification purposes. If you
|
||||
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.
|
||||
"""
|
||||
assert funcargs is None or isinstance(funcargs, dict)
|
||||
if funcargs is not None:
|
||||
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)
|
||||
else:
|
||||
funcargs = {}
|
||||
|
@ -722,11 +721,11 @@ class IDMaker:
|
|||
return "-".join(l)
|
||||
|
||||
|
||||
def showfuncargs(config):
|
||||
def showfixtures(config):
|
||||
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()
|
||||
if session.items:
|
||||
plugins = session.items[0].getplugins()
|
||||
|
@ -735,7 +734,7 @@ def _showfuncargs_main(config, session):
|
|||
curdir = py.path.local()
|
||||
tw = py.io.TerminalWriter()
|
||||
verbose = config.getvalue("verbose")
|
||||
argprefix = session.funcargmanager._argprefix
|
||||
argprefix = session._fixturemanager._argprefix
|
||||
for plugin in plugins:
|
||||
available = []
|
||||
for name, factory in vars(plugin).items():
|
||||
|
@ -854,7 +853,7 @@ class RaisesContext(object):
|
|||
# the basic py.test Function item
|
||||
#
|
||||
_dummy = object()
|
||||
class Function(FunctionMixin, pytest.Item):
|
||||
class Function(FunctionMixin, pytest.Item, FuncargnamesCompatAttr):
|
||||
""" a Function Item is responsible for setting up and executing a
|
||||
Python test function.
|
||||
"""
|
||||
|
@ -876,11 +875,11 @@ class Function(FunctionMixin, pytest.Item):
|
|||
self.param = callspec.param
|
||||
else:
|
||||
self.funcargs = {}
|
||||
self._request = req = FuncargRequest(self)
|
||||
self._request = req = FixtureRequest(self)
|
||||
#req._discoverfactories()
|
||||
if callobj is not _dummy:
|
||||
self.obj = callobj
|
||||
self.funcargnames = self._getfixturenames()
|
||||
self.fixturenames = self._getfuncargnames()
|
||||
|
||||
for name, val in (py.builtin._getfuncdict(self.obj) or {}).items():
|
||||
setattr(self.markers, name, val)
|
||||
|
@ -888,9 +887,10 @@ class Function(FunctionMixin, pytest.Item):
|
|||
for name, val in keywords.items():
|
||||
setattr(self.markers, name, val)
|
||||
|
||||
def _getfixturenames(self):
|
||||
|
||||
def _getfuncargnames(self):
|
||||
startindex = int(self.cls is not None)
|
||||
return (self.session.funcargmanager._autofixtures +
|
||||
return (self.session._fixturemanager._autofixtures +
|
||||
getfuncargnames(self.obj, startindex=startindex))
|
||||
|
||||
@property
|
||||
|
@ -921,7 +921,7 @@ class Function(FunctionMixin, pytest.Item):
|
|||
super(Function, self).setup()
|
||||
#if hasattr(self, "_request"):
|
||||
# self._request._callsetup()
|
||||
fillfuncargs(self)
|
||||
fillfixtures(self)
|
||||
|
||||
def __eq__(self, other):
|
||||
try:
|
||||
|
@ -960,8 +960,8 @@ def scopeproperty(name=None, doc=None):
|
|||
return decoratescope
|
||||
|
||||
|
||||
class FuncargRequest:
|
||||
""" A request for function arguments from a test or setup function.
|
||||
class FixtureRequest(FuncargnamesCompatAttr):
|
||||
""" A request for fixtures from a test or setup function.
|
||||
|
||||
A request object gives access to attributes of the requesting
|
||||
test context. It has an optional ``param`` attribute in case
|
||||
|
@ -976,38 +976,38 @@ class FuncargRequest:
|
|||
self.scope = "function"
|
||||
self.getparent = pyfuncitem.getparent
|
||||
self._funcargs = self._pyfuncitem.funcargs.copy()
|
||||
self._name2factory = {}
|
||||
self.funcargmanager = pyfuncitem.session.funcargmanager
|
||||
self._arg2fixturedeflist = {}
|
||||
self._fixturemanager = pyfuncitem.session._fixturemanager
|
||||
self._currentarg = None
|
||||
self.parentid = pyfuncitem.parent.nodeid
|
||||
self.funcargnames, self._arg2facdeflist_ = \
|
||||
self.funcargmanager.getallfuncargnames(
|
||||
self._parentid = pyfuncitem.parent.nodeid
|
||||
self.fixturenames, self._arg2fixturedeflist_ = \
|
||||
self._fixturemanager.getfixtureclosure(
|
||||
getfuncargnames(self.function), # XXX _pyfuncitem...
|
||||
pyfuncitem.parent)
|
||||
self._factorystack = []
|
||||
self._fixturestack = []
|
||||
|
||||
@property
|
||||
def node(self):
|
||||
""" underlying collection node (depends on request scope)"""
|
||||
return self._getscopeitem(self.scope)
|
||||
|
||||
def _getfaclist(self, argname):
|
||||
facdeflist = self._name2factory.get(argname, None)
|
||||
getfactb = None
|
||||
def _getfixturedeflist(self, argname):
|
||||
fixturedeflist = self._arg2fixturedeflist.get(argname, None)
|
||||
getfixturetb = None
|
||||
function = None
|
||||
if facdeflist is None:
|
||||
if self._factorystack:
|
||||
function = self._factorystack[-1].func
|
||||
getfactb = lambda: self._factorystack[:-1]
|
||||
if fixturedeflist is None:
|
||||
if self._fixturestack:
|
||||
function = self._fixturestack[-1].func
|
||||
getfixturetb = lambda: self._fixturestack[:-1]
|
||||
else:
|
||||
function = self.function
|
||||
facdeflist = self.funcargmanager.getfactorylist(
|
||||
argname, self.parentid)
|
||||
self._name2factory[argname] = facdeflist
|
||||
if not facdeflist:
|
||||
self.funcargmanager._raiselookupfailed(argname, function,
|
||||
self.parentid, getfactb)
|
||||
return facdeflist
|
||||
fixturedeflist = self._fixturemanager.getfixturedeflist(
|
||||
argname, self._parentid)
|
||||
self._arg2fixturedeflist[argname] = fixturedeflist
|
||||
if not fixturedeflist:
|
||||
self._fixturemanager._raiselookupfailed(argname, function,
|
||||
self._parentid, getfixturetb)
|
||||
return fixturedeflist
|
||||
|
||||
@property
|
||||
def config(self):
|
||||
|
@ -1060,7 +1060,7 @@ class FuncargRequest:
|
|||
"""add finalizer/teardown function to be called after the
|
||||
last test within the requesting test context finished
|
||||
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)
|
||||
|
||||
def _addfinalizer(self, finalizer, scope):
|
||||
|
@ -1084,15 +1084,15 @@ class FuncargRequest:
|
|||
self.node.applymarker(marker)
|
||||
|
||||
def raiseerror(self, msg):
|
||||
""" raise a FuncargLookupError with the given message. """
|
||||
raise self.funcargmanager.FuncargLookupError(self.function, msg)
|
||||
""" raise a FixtureLookupError with the given message. """
|
||||
raise self._fixturemanager.FixtureLookupError(self.function, msg)
|
||||
|
||||
|
||||
def _fillfuncargs(self):
|
||||
def _fillfixtures(self):
|
||||
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:
|
||||
item.funcargs[argname] = self.getfuncargvalue(argname)
|
||||
|
||||
|
@ -1100,9 +1100,9 @@ class FuncargRequest:
|
|||
""" (deprecated) Return a testing resource managed by ``setup`` &
|
||||
``teardown`` calls. ``scope`` and ``extrakey`` determine when the
|
||||
``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
|
||||
on a funcarg factory and register a finalizer through
|
||||
on a fixture function and register a finalizer through
|
||||
``request.addfinalizer()``.
|
||||
|
||||
:arg teardown: function receiving a previously setup resource.
|
||||
|
@ -1151,27 +1151,27 @@ class FuncargRequest:
|
|||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
factorydeflist = self._getfaclist(argname)
|
||||
except FuncargLookupError:
|
||||
fixturedeflist = self._getfixturedeflist(argname)
|
||||
except FixtureLookupError:
|
||||
if argname == "request":
|
||||
return self
|
||||
raise
|
||||
factorydef = factorydeflist.pop()
|
||||
self._factorystack.append(factorydef)
|
||||
fixturedef = fixturedeflist.pop()
|
||||
self._fixturestack.append(fixturedef)
|
||||
try:
|
||||
result = self._getfuncargvalue(factorydef)
|
||||
result = self._getfuncargvalue(fixturedef)
|
||||
self._funcargs[argname] = result
|
||||
return result
|
||||
finally:
|
||||
self._factorystack.pop()
|
||||
self._fixturestack.pop()
|
||||
|
||||
def _getfuncargvalue(self, factorydef):
|
||||
if factorydef.active:
|
||||
return factorydef.cached_result
|
||||
def _getfuncargvalue(self, fixturedef):
|
||||
if fixturedef.active:
|
||||
return fixturedef.cached_result
|
||||
|
||||
# prepare request scope and param attributes before
|
||||
# calling into factory
|
||||
argname = factorydef.argname
|
||||
argname = fixturedef.argname
|
||||
node = self._pyfuncitem
|
||||
mp = monkeypatch()
|
||||
mp.setattr(self, '_currentarg', argname)
|
||||
|
@ -1181,7 +1181,7 @@ class FuncargRequest:
|
|||
pass
|
||||
else:
|
||||
mp.setattr(self, 'param', param, raising=False)
|
||||
scope = factorydef.scope
|
||||
scope = fixturedef.scope
|
||||
if scope is not None:
|
||||
__tracebackhide__ = True
|
||||
if scopemismatch(self.scope, scope):
|
||||
|
@ -1195,20 +1195,20 @@ class FuncargRequest:
|
|||
mp.setattr(self, "scope", scope)
|
||||
|
||||
# prepare finalization according to scope
|
||||
self.session._setupstate.addfinalizer(factorydef.finish, self.node)
|
||||
self.funcargmanager.addargfinalizer(factorydef.finish, argname)
|
||||
for subargname in factorydef.funcargnames: # XXX all deps?
|
||||
self.funcargmanager.addargfinalizer(factorydef.finish, subargname)
|
||||
mp.setattr(self, "addfinalizer", factorydef.addfinalizer)
|
||||
self.session._setupstate.addfinalizer(fixturedef.finish, self.node)
|
||||
self._fixturemanager.addargfinalizer(fixturedef.finish, argname)
|
||||
for subargname in fixturedef.fixturenames: # XXX all deps?
|
||||
self._fixturemanager.addargfinalizer(fixturedef.finish, subargname)
|
||||
mp.setattr(self, "addfinalizer", fixturedef.addfinalizer)
|
||||
# finally perform the factory call
|
||||
val = factorydef.execute(request=self)
|
||||
val = fixturedef.execute(request=self)
|
||||
mp.undo()
|
||||
return val
|
||||
|
||||
def _factorytraceback(self):
|
||||
lines = []
|
||||
for factorydef in self._factorystack:
|
||||
factory = factorydef.func
|
||||
for fixturedef in self._fixturestack:
|
||||
factory = fixturedef.func
|
||||
fs, lineno = getfslineno(factory)
|
||||
p = self._pyfuncitem.session.fspath.bestrelpath(fs)
|
||||
args = inspect.formatargspec(*inspect.getargspec(factory))
|
||||
|
@ -1232,10 +1232,10 @@ class FuncargRequest:
|
|||
raise ValueError("unknown finalization scope %r" %(scope,))
|
||||
|
||||
def __repr__(self):
|
||||
return "<FuncargRequest for %r>" %(self._pyfuncitem)
|
||||
return "<FixtureRequest for %r>" %(self._pyfuncitem)
|
||||
|
||||
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)
|
||||
"""
|
||||
|
||||
|
@ -1249,14 +1249,14 @@ def slice_kwargs(names, kwargs):
|
|||
new_kwargs[name] = kwargs[name]
|
||||
return new_kwargs
|
||||
|
||||
class FuncargLookupError(LookupError):
|
||||
class FixtureLookupError(LookupError):
|
||||
""" could not find a factory. """
|
||||
def __init__(self, function, msg, factblines=None):
|
||||
self.function = function
|
||||
self.msg = msg
|
||||
self.factblines = factblines
|
||||
|
||||
class FuncargLookupErrorRepr(TerminalRepr):
|
||||
class FixtureLookupErrorRepr(TerminalRepr):
|
||||
def __init__(self, filename, firstlineno, deflines, errorstring, factblines):
|
||||
self.deflines = deflines
|
||||
self.errorstring = errorstring
|
||||
|
@ -1268,10 +1268,10 @@ class FuncargLookupErrorRepr(TerminalRepr):
|
|||
tw.line()
|
||||
if self.factblines:
|
||||
tw.line(' dependency of:')
|
||||
for factorydef in self.factblines:
|
||||
for fixturedef in self.factblines:
|
||||
tw.line(' %s in %s' % (
|
||||
factorydef.argname,
|
||||
factorydef.baseid,
|
||||
fixturedef.argname,
|
||||
fixturedef.baseid,
|
||||
))
|
||||
tw.line()
|
||||
for line in self.deflines:
|
||||
|
@ -1281,15 +1281,15 @@ class FuncargLookupErrorRepr(TerminalRepr):
|
|||
tw.line()
|
||||
tw.line("%s:%d" % (self.filename, self.firstlineno+1))
|
||||
|
||||
class FuncargManager:
|
||||
class FixtureManager:
|
||||
_argprefix = "pytest_funcarg__"
|
||||
FuncargLookupError = FuncargLookupError
|
||||
FuncargLookupErrorRepr = FuncargLookupErrorRepr
|
||||
FixtureLookupError = FixtureLookupError
|
||||
FixtureLookupErrorRepr = FixtureLookupErrorRepr
|
||||
|
||||
def __init__(self, session):
|
||||
self.session = session
|
||||
self.config = session.config
|
||||
self.arg2facspec = {}
|
||||
self.arg2fixturedeflist = {}
|
||||
self._seenplugins = set()
|
||||
self._holderobjseen = set()
|
||||
self._arg2finish = {}
|
||||
|
@ -1319,41 +1319,44 @@ class FuncargManager:
|
|||
for plugin in plugins:
|
||||
self.pytest_plugin_registered(plugin)
|
||||
|
||||
def getallfuncargnames(self, funcargnames, parentnode):
|
||||
# collect the closure of all funcargs, starting with
|
||||
# funcargnames as the initial set
|
||||
# we populate and return a arg2facdeflist mapping
|
||||
# so that the caller can reuse it and does not have to re-discover
|
||||
# factories again for each funcargname
|
||||
def getfixtureclosure(self, fixturenames, parentnode):
|
||||
# collect the closure of all funcargs, starting with the given
|
||||
# fixturenames as the initial set. As we have to visit all
|
||||
# factory definitions anyway, we also return a arg2fixturedeflist
|
||||
# mapping so that the caller can reuse it and does not have
|
||||
# to re-discover fixturedefs again for each fixturename
|
||||
# (discovering matching fixtures for a given name/node is expensive)
|
||||
|
||||
parentid = parentnode.nodeid
|
||||
funcargnames = self._autofixtures + list(funcargnames)
|
||||
fixturenames_closure = list(self._autofixtures)
|
||||
def merge(otherlist):
|
||||
for arg in otherlist:
|
||||
if arg not in funcargnames:
|
||||
funcargnames.append(arg)
|
||||
arg2facdeflist = {}
|
||||
if arg not in fixturenames_closure:
|
||||
fixturenames_closure.append(arg)
|
||||
merge(fixturenames)
|
||||
arg2fixturedeflist = {}
|
||||
lastlen = -1
|
||||
while lastlen != len(funcargnames):
|
||||
lastlen = len(funcargnames)
|
||||
for argname in list(funcargnames):
|
||||
if argname in arg2facdeflist:
|
||||
while lastlen != len(fixturenames_closure):
|
||||
lastlen = len(fixturenames_closure)
|
||||
for argname in fixturenames_closure:
|
||||
if argname in arg2fixturedeflist:
|
||||
continue
|
||||
facdeflist = self.getfactorylist(argname, parentid)
|
||||
arg2facdeflist[argname] = facdeflist
|
||||
if facdeflist is not None:
|
||||
for facdef in facdeflist:
|
||||
merge(facdef.funcargnames)
|
||||
return funcargnames, arg2facdeflist
|
||||
fixturedeflist = self.getfixturedeflist(argname, parentid)
|
||||
arg2fixturedeflist[argname] = fixturedeflist
|
||||
if fixturedeflist is not None:
|
||||
for fixturedef in fixturedeflist:
|
||||
merge(fixturedef.fixturenames)
|
||||
return fixturenames_closure, arg2fixturedeflist
|
||||
|
||||
def pytest_generate_tests(self, metafunc):
|
||||
for argname in metafunc.funcargnames:
|
||||
faclist = metafunc._arg2facdeflist[argname]
|
||||
for argname in metafunc.fixturenames:
|
||||
faclist = metafunc._arg2fixturedeflist[argname]
|
||||
if faclist is None:
|
||||
continue # will raise FuncargLookupError at setup time
|
||||
for facdef in faclist:
|
||||
if facdef.params is not None:
|
||||
metafunc.parametrize(argname, facdef.params, indirect=True,
|
||||
scope=facdef.scope)
|
||||
continue # will raise FixtureLookupError at setup time
|
||||
for fixturedef in faclist:
|
||||
if fixturedef.params is not None:
|
||||
metafunc.parametrize(argname, fixturedef.params, indirect=True,
|
||||
scope=fixturedef.scope)
|
||||
|
||||
def pytest_collection_modifyitems(self, items):
|
||||
# separate parametrized setups
|
||||
|
@ -1394,7 +1397,7 @@ class FuncargManager:
|
|||
obj = getattr(holderobj, name)
|
||||
if not callable(obj):
|
||||
continue
|
||||
# fixture functions have a pytest_funcarg__ prefix
|
||||
# fixture functions have a pytest_funcarg__ prefix (pre-2.3 style)
|
||||
# or are "@pytest.fixture" marked
|
||||
marker = getattr(obj, "_pytestfixturefunction", None)
|
||||
if marker is None:
|
||||
|
@ -1408,42 +1411,42 @@ class FuncargManager:
|
|||
continue
|
||||
else:
|
||||
assert not name.startswith(self._argprefix)
|
||||
factorydef = FactoryDef(self, nodeid, name, obj,
|
||||
fixturedef = FixtureDef(self, nodeid, name, obj,
|
||||
marker.scope, marker.params,
|
||||
unittest=unittest)
|
||||
faclist = self.arg2facspec.setdefault(name, [])
|
||||
faclist.append(factorydef)
|
||||
faclist = self.arg2fixturedeflist.setdefault(name, [])
|
||||
faclist.append(fixturedef)
|
||||
if marker.autoactive:
|
||||
# make sure the self._autofixtures list is always sorted
|
||||
# by scope, scopenum 0 is session
|
||||
self._autofixtures.append(name)
|
||||
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:
|
||||
factorydeflist = self.arg2facspec[argname]
|
||||
fixturedeflist = self.arg2fixturedeflist[argname]
|
||||
except KeyError:
|
||||
return None
|
||||
else:
|
||||
return list(self._matchfactories(factorydeflist, nodeid))
|
||||
return list(self._matchfactories(fixturedeflist, nodeid))
|
||||
|
||||
def _matchfactories(self, factorydeflist, nodeid):
|
||||
for factorydef in factorydeflist:
|
||||
if nodeid.startswith(factorydef.baseid):
|
||||
yield factorydef
|
||||
def _matchfactories(self, fixturedeflist, nodeid):
|
||||
for fixturedef in fixturedeflist:
|
||||
if nodeid.startswith(fixturedef.baseid):
|
||||
yield fixturedef
|
||||
|
||||
def _raiselookupfailed(self, argname, function, nodeid, getfactb=None):
|
||||
def _raiselookupfailed(self, argname, function, nodeid, getfixturetb=None):
|
||||
available = []
|
||||
for name, facdef in self.arg2facspec.items():
|
||||
faclist = list(self._matchfactories(facdef, nodeid))
|
||||
for name, fixturedef in self.arg2fixturedeflist.items():
|
||||
faclist = list(self._matchfactories(fixturedef, nodeid))
|
||||
if faclist:
|
||||
available.append(name)
|
||||
msg = "LookupError: no factory found for argument %r" % (argname,)
|
||||
msg += "\n available funcargs: %s" %(", ".join(available),)
|
||||
msg += "\n use 'py.test --funcargs [testpath]' for help on them."
|
||||
lines = getfactb and getfactb() or []
|
||||
raise FuncargLookupError(function, msg, lines)
|
||||
msg += "\n use 'py.test --fixtures [testpath]' for help on them."
|
||||
lines = getfixturetb and getfixturetb() or []
|
||||
raise FixtureLookupError(function, msg, lines)
|
||||
|
||||
def addargfinalizer(self, finalizer, argname):
|
||||
l = self._arg2finish.setdefault(argname, [])
|
||||
|
@ -1456,11 +1459,11 @@ class FuncargManager:
|
|||
except ValueError:
|
||||
pass
|
||||
|
||||
class FactoryDef:
|
||||
class FixtureDef:
|
||||
""" 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):
|
||||
self.funcargmanager = funcargmanager
|
||||
self._fixturemanager = fixturenanager
|
||||
self.baseid = baseid
|
||||
self.func = func
|
||||
self.argname = argname
|
||||
|
@ -1468,7 +1471,7 @@ class FactoryDef:
|
|||
self.scopenum = scopes.index(scope or "function")
|
||||
self.params = params
|
||||
startindex = unittest and 1 or None
|
||||
self.funcargnames = getfuncargnames(func, startindex=startindex)
|
||||
self.fixturenames = getfuncargnames(func, startindex=startindex)
|
||||
self.unittest = unittest
|
||||
self.active = False
|
||||
self._finalizer = []
|
||||
|
@ -1481,14 +1484,14 @@ class FactoryDef:
|
|||
func = self._finalizer.pop()
|
||||
func()
|
||||
# check neccesity of next commented call
|
||||
self.funcargmanager.removefinalizer(self.finish)
|
||||
self._fixturemanager.removefinalizer(self.finish)
|
||||
self.active = False
|
||||
#print "finished", self
|
||||
#del self.cached_result
|
||||
|
||||
def execute(self, request):
|
||||
kwargs = {}
|
||||
for newname in self.funcargnames:
|
||||
for newname in self.fixturenames:
|
||||
kwargs[newname] = request.getfuncargvalue(newname)
|
||||
if self.unittest:
|
||||
result = self.func(request.instance, **kwargs)
|
||||
|
@ -1499,7 +1502,7 @@ class FactoryDef:
|
|||
return result
|
||||
|
||||
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):
|
||||
# XXX merge with main.py's varnames
|
||||
|
|
|
@ -21,7 +21,7 @@ def pytest_pycollect_makeitem(collector, name, obj):
|
|||
|
||||
class UnitTestCase(pytest.Class):
|
||||
def collect(self):
|
||||
self.session.funcargmanager._parsefactories(self.obj, self.nodeid,
|
||||
self.session._fixturemanager._parsefactories(self.obj, self.nodeid,
|
||||
unittest=True)
|
||||
loader = py.std.unittest.TestLoader()
|
||||
module = self.getparent(pytest.Module).obj
|
||||
|
@ -52,8 +52,8 @@ class UnitTestCase(pytest.Class):
|
|||
class TestCaseFunction(pytest.Function):
|
||||
_excinfo = None
|
||||
|
||||
def _getfixturenames(self):
|
||||
return list(self.session.funcargmanager._autofixtures)
|
||||
def _getfuncargnames(self):
|
||||
return list(self.session._fixturemanager._autofixtures)
|
||||
|
||||
def setup(self):
|
||||
self._testcase = self.parent.obj(self.name)
|
||||
|
@ -65,7 +65,7 @@ class TestCaseFunction(pytest.Function):
|
|||
if hasattr(self._testcase, 'setup_method'):
|
||||
self._testcase.setup_method(self._obj)
|
||||
if hasattr(self, "_request"):
|
||||
self._request._fillfuncargs()
|
||||
self._request._fillfixtures()
|
||||
|
||||
def teardown(self):
|
||||
if hasattr(self._testcase, 'teardown_method'):
|
||||
|
|
|
@ -25,7 +25,7 @@ Builtin resources / function arguments
|
|||
You can ask for available builtin or project-custom
|
||||
:ref:`function arguments <funcargs>` by typing::
|
||||
|
||||
$ py.test --funcargs
|
||||
$ py.test --fixtures
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.3 -- pytest-2.3.0.dev2
|
||||
plugins: xdist, bugzilla, cache, oejskit, pep8, cov
|
||||
|
|
|
@ -15,7 +15,7 @@ def test_generative(param1, param2):
|
|||
assert param1 * 2 < param2
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if 'param1' in metafunc.funcargnames:
|
||||
if 'param1' in metafunc.fixturenames:
|
||||
metafunc.addcall(funcargs=dict(param1=3, param2=6))
|
||||
|
||||
class TestFailing(object):
|
||||
|
|
|
@ -13,9 +13,9 @@ example: specifying and selecting acceptance tests
|
|||
help="run (slow) acceptance tests")
|
||||
|
||||
def pytest_funcarg__accept(request):
|
||||
return AcceptFuncarg(request)
|
||||
return AcceptFixture(request)
|
||||
|
||||
class AcceptFuncarg:
|
||||
class AcceptFixture:
|
||||
def __init__(self, request):
|
||||
if not request.config.option.acceptance:
|
||||
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
|
||||
the test will get skipped with an appropriate message. Otherwise
|
||||
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
|
||||
the output.
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ Now we add a test configuration like this::
|
|||
help="run all combinations")
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if 'param1' in metafunc.funcargnames:
|
||||
if 'param1' in metafunc.fixturenames:
|
||||
if metafunc.config.option.all:
|
||||
end = 5
|
||||
else:
|
||||
|
@ -213,7 +213,7 @@ creates a database object for the actual test invocations::
|
|||
# content of conftest.py
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if 'db' in metafunc.funcargnames:
|
||||
if 'db' in metafunc.fixturenames:
|
||||
metafunc.parametrize("db", ['d1', 'd2'], indirect=True)
|
||||
|
||||
class DB1:
|
||||
|
|
|
@ -126,11 +126,11 @@ the ``MYARG`` function argument.
|
|||
.. note::
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
|
|
@ -676,6 +676,6 @@ and provides methods to:
|
|||
* to add finalizers/teardowns to be invoked when the last
|
||||
test of the requesting test context executes
|
||||
|
||||
.. autoclass:: _pytest.python.FuncargRequest()
|
||||
.. autoclass:: _pytest.python.FixtureRequest()
|
||||
:members:
|
||||
|
||||
|
|
|
@ -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
|
||||
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.
|
||||
|
||||
All of these limitations are addressed with pytest-2.3 and its
|
||||
|
|
|
@ -29,7 +29,7 @@ different variants of test resources to test with.
|
|||
The basic mechanism for injecting objects is called the *funcarg
|
||||
mechanism* because objects are injected when a test or setup
|
||||
**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`_
|
||||
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
|
||||
|
@ -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
|
||||
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 their signature. pytest additionally offers powerful xunit-style
|
||||
: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::
|
||||
|
||||
py.test --funcargs test_simplefactory.py
|
||||
py.test --fixtures test_simplefactory.py
|
||||
|
||||
to see available function arguments.
|
||||
|
||||
|
@ -289,7 +289,7 @@ that option::
|
|||
help="run all combinations")
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if 'param1' in metafunc.funcargnames:
|
||||
if 'param1' in metafunc.fixturenames:
|
||||
if metafunc.config.option.all:
|
||||
end = 5
|
||||
else:
|
||||
|
@ -336,7 +336,7 @@ They help to inspect a testfunction and to generate tests
|
|||
according to test configuration or values specified
|
||||
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
|
||||
|
||||
|
@ -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.funcargnames``: alias for ``fixturenames``, for pre-2.3 compatibility
|
||||
|
||||
.. automethod:: Metafunc.parametrize
|
||||
.. 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
|
||||
============================================================
|
||||
|
||||
**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:
|
||||
|
||||
* 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
|
||||
``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
|
||||
the `automatic per-resource grouping`_ of tests.
|
||||
|
||||
.. note::
|
||||
|
||||
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
|
||||
unmodified.
|
||||
|
||||
|
|
|
@ -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::
|
||||
|
||||
py.test --funcargs # shows builtin and custom function arguments
|
||||
py.test --fixtures # shows builtin and custom function arguments
|
||||
|
||||
Where to go next
|
||||
-------------------------------------
|
||||
|
|
|
@ -24,7 +24,7 @@ command line options
|
|||
traceback print mode (long/short/line/no).
|
||||
``--fulltrace``
|
||||
don't cut any tracebacks (default is to cut).
|
||||
``--funcargs``
|
||||
``--fixtures``
|
||||
show available function arguments, sorted by plugin
|
||||
|
||||
Start improving this plugin in 30 seconds
|
||||
|
|
|
@ -26,7 +26,7 @@ Getting help on version, option names, environment variables
|
|||
::
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ Python インタープリターの対話モードから次のように入力す
|
|||
|
||||
次のように入力して、利用できる組み込みまたはプロジェクトカスタムの :ref:`関数の引数 <funcargs>` を確認できます。
|
||||
|
||||
| $ py.test --funcargs
|
||||
| $ py.test --fixtures
|
||||
| ====================== test session starts =======================
|
||||
| platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||
| collected 0 items
|
||||
|
@ -98,7 +98,7 @@ Python インタープリターの対話モードから次のように入力す
|
|||
| ======================== in 0.00 seconds ========================
|
||||
|
||||
..
|
||||
$ py.test --funcargs
|
||||
$ py.test --fixtures
|
||||
=========================== test session starts ============================
|
||||
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||
collected 0 items
|
||||
|
|
|
@ -15,7 +15,7 @@ def test_generative(param1, param2):
|
|||
assert param1 * 2 < param2
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if 'param1' in metafunc.funcargnames:
|
||||
if 'param1' in metafunc.fixturenames:
|
||||
metafunc.addcall(funcargs=dict(param1=3, param2=6))
|
||||
|
||||
class TestFailing(object):
|
||||
|
|
|
@ -13,9 +13,9 @@ example: specifying and selecting acceptance tests
|
|||
help="run (slow) acceptance tests")
|
||||
|
||||
def pytest_funcarg__accept(request):
|
||||
return AcceptFuncarg(request)
|
||||
return AcceptFixture(request)
|
||||
|
||||
class AcceptFuncarg:
|
||||
class AcceptFixture:
|
||||
def __init__(self, request):
|
||||
if not request.config.option.acceptance:
|
||||
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
|
||||
the test will get skipped with an appropriate message. Otherwise
|
||||
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
|
||||
the output.
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ def pytest_generate_tests(metafunc):
|
|||
# over the python interpreters of our list above - the actual
|
||||
# setup and lookup of interpreters in the python1/python2 factories
|
||||
# respectively.
|
||||
for arg in metafunc.funcargnames:
|
||||
for arg in metafunc.fixturenames:
|
||||
if arg in ("python1", "python2"):
|
||||
metafunc.parametrize(arg, pythonlist, indirect=True)
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ py.test は、簡単にパラメーターをテスト関数へ渡せます。パ
|
|||
help="run all combinations")
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if 'param1' in metafunc.funcargnames:
|
||||
if 'param1' in metafunc.fixturenames:
|
||||
if metafunc.config.option.all:
|
||||
end = 5
|
||||
else:
|
||||
|
@ -266,7 +266,7 @@ Robert Collins による標準ライブラリの unittest フレームワーク
|
|||
# conftest.py の内容
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if 'db' in metafunc.funcargnames:
|
||||
if 'db' in metafunc.fixturenames:
|
||||
metafunc.parametrize("db", ['d1', 'd2'], indirect=True)
|
||||
|
||||
class DB1:
|
||||
|
|
|
@ -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?
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
..
|
||||
|
|
|
@ -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
|
||||
|
@ -171,7 +171,7 @@ py.test には :ref:`builtinfuncargs` が付属していて、そのサンプル
|
|||
.. _`xUnit style`: xunit_setup.html
|
||||
|
||||
|
||||
.. _`funcarg factory`:
|
||||
.. _`fixture function`:
|
||||
.. _factory:
|
||||
|
||||
funcarg **request** オブジェクト
|
||||
|
@ -182,24 +182,24 @@ funcarg **request** オブジェクト
|
|||
=============================================
|
||||
|
||||
..
|
||||
Each funcarg factory receives a **request** object tied to a specific test
|
||||
function call. A request object is passed to a funcarg factory and provides
|
||||
Each fixture function receives a **request** object tied to a specific test
|
||||
function call. A request object is passed to a fixture function and provides
|
||||
access to test configuration and context:
|
||||
|
||||
funcarg ファクトリー関数は、特別なテスト関数呼び出しに関連付けられた **request** オブジェクトを受け取ります。request オブジェクトは funcarg ファクトリーへ渡されて、テスト設定とコンテキストへのアクセスを提供します:
|
||||
|
||||
.. autoclass:: _pytest.python.FuncargRequest()
|
||||
.. autoclass:: _pytest.python.FixtureRequest()
|
||||
:members: function,cls,module,keywords,config
|
||||
|
||||
.. _`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`:
|
||||
|
@ -236,7 +236,7 @@ funcarg ファクトリー関数は、特別なテスト関数呼び出しに関
|
|||
|
||||
# test_example.py の内容
|
||||
def pytest_generate_tests(metafunc):
|
||||
if "numiter" in metafunc.funcargnames:
|
||||
if "numiter" in metafunc.fixturenames:
|
||||
metafunc.parametrize("numiter", range(10))
|
||||
|
||||
def test_func(numiter):
|
||||
|
@ -329,9 +329,9 @@ funcarg ファクトリー関数は、特別なテスト関数呼び出しに関
|
|||
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
|
||||
|
|
|
@ -265,7 +265,7 @@ py.test は :ref:`標準的なテスト探索ルール <test discovery>` に従
|
|||
|
||||
組み込みの :ref:`funcargs` を把握するには、次のコマンドを実行します::
|
||||
|
||||
py.test --funcargs # 組み込み/カスタムの関数の引数を表示する
|
||||
py.test --fixtures # 組み込み/カスタムの関数の引数を表示する
|
||||
|
||||
..
|
||||
Where to go next
|
||||
|
|
|
@ -24,7 +24,7 @@ command line options
|
|||
traceback print mode (long/short/line/no).
|
||||
``--fulltrace``
|
||||
don't cut any tracebacks (default is to cut).
|
||||
``--funcargs``
|
||||
``--fixtures``
|
||||
show available function arguments, sorted by plugin
|
||||
|
||||
Start improving this plugin in 30 seconds
|
||||
|
|
|
@ -43,7 +43,7 @@ Python 2.5 か、それ以上のバージョンを使っているなら、コマ
|
|||
::
|
||||
|
||||
py.test --version # pytest がインポートされた場所を表示
|
||||
py.test --funcargs # 利用できる組み込みの関数引数を表示
|
||||
py.test --fixtures # 利用できる組み込みの関数引数を表示
|
||||
py.test -h | --help # コマンドラインと設定ファイルオプションのヘルプを表示
|
||||
|
||||
..
|
||||
|
|
|
@ -64,7 +64,7 @@ def pytest_generate_tests(metafunc):
|
|||
for name, l in multi.kwargs.items():
|
||||
for val in l:
|
||||
metafunc.addcall(funcargs={name: val})
|
||||
elif 'anypython' in metafunc.funcargnames:
|
||||
elif 'anypython' in metafunc.fixturenames:
|
||||
for name in ('python2.4', 'python2.5', 'python2.6',
|
||||
'python2.7', 'python3.1', 'pypy', 'jython'):
|
||||
metafunc.addcall(id=name, param=name)
|
||||
|
|
|
@ -363,7 +363,7 @@ class TestLoggingInteraction:
|
|||
assert 'operation on closed file' not in result.stderr.str()
|
||||
|
||||
|
||||
class TestCaptureFuncarg:
|
||||
class TestCaptureFixture:
|
||||
def test_std_functional(self, testdir):
|
||||
reprec = testdir.inline_runsource("""
|
||||
def test_hello(capsys):
|
||||
|
|
|
@ -2,7 +2,7 @@ import py, pytest
|
|||
from _pytest.config import Conftest
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if "basedir" in metafunc.funcargnames:
|
||||
if "basedir" in metafunc.fixturenames:
|
||||
metafunc.addcall(param="global")
|
||||
metafunc.addcall(param="inpackage")
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ def test_help(testdir):
|
|||
*setup.cfg*
|
||||
*minversion*
|
||||
*to see*markers*py.test --markers*
|
||||
*to see*funcargs*py.test --funcargs*
|
||||
*to see*fixtures*py.test --fixtures*
|
||||
""")
|
||||
|
||||
def test_collectattr():
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import pytest, py, sys
|
||||
from _pytest import python as funcargs
|
||||
from _pytest.python import FuncargLookupError
|
||||
from _pytest.python import FixtureLookupError
|
||||
|
||||
class TestModule:
|
||||
def test_failing_import(self, testdir):
|
||||
|
@ -276,10 +276,10 @@ class TestFunction:
|
|||
assert hasattr(modcol.obj, 'test_func')
|
||||
|
||||
def test_function_equality(self, testdir, tmpdir):
|
||||
from _pytest.python import FuncargManager
|
||||
from _pytest.python import FixtureManager
|
||||
config = testdir.parseconfigure()
|
||||
session = testdir.Session(config)
|
||||
session.funcargmanager = FuncargManager(session)
|
||||
session._fixturemanager = FixtureManager(session)
|
||||
def func1():
|
||||
pass
|
||||
def func2():
|
||||
|
@ -542,10 +542,10 @@ def test_getfuncargnames():
|
|||
pass
|
||||
assert funcargs.getfuncargnames(A) == ["x"]
|
||||
|
||||
class TestFillFuncArgs:
|
||||
class TestFillFixtures:
|
||||
def test_fillfuncargs_exposed(self):
|
||||
# used by oejskit
|
||||
assert pytest._fillfuncargs == funcargs.fillfuncargs
|
||||
# used by oejskit, kept for compatibility
|
||||
assert pytest._fillfuncargs == funcargs.fillfixtures
|
||||
|
||||
def test_funcarg_lookupfails(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
|
@ -572,7 +572,7 @@ class TestFillFuncArgs:
|
|||
def test_func(some, other):
|
||||
pass
|
||||
""")
|
||||
funcargs.fillfuncargs(item)
|
||||
funcargs.fillfixtures(item)
|
||||
assert len(item.funcargs) == 2
|
||||
assert item.funcargs['some'] == "test_func"
|
||||
assert item.funcargs['other'] == 42
|
||||
|
@ -611,7 +611,7 @@ class TestRequest:
|
|||
def pytest_funcarg__something(request): pass
|
||||
def test_func(something): pass
|
||||
""")
|
||||
req = funcargs.FuncargRequest(item)
|
||||
req = funcargs.FixtureRequest(item)
|
||||
assert req.function == item.obj
|
||||
assert req.keywords == item.keywords
|
||||
assert hasattr(req.module, 'test_func')
|
||||
|
@ -632,7 +632,7 @@ class TestRequest:
|
|||
assert req.cls.__name__ == "TestB"
|
||||
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("""
|
||||
def pytest_funcarg__something(request):
|
||||
pass
|
||||
|
@ -642,9 +642,9 @@ class TestRequest:
|
|||
""")
|
||||
item1, = testdir.genitems([modcol])
|
||||
assert item1.name == "test_method"
|
||||
name2factory = funcargs.FuncargRequest(item1)._name2factory
|
||||
assert len(name2factory) == 1
|
||||
assert name2factory[0].__name__ == "pytest_funcarg__something"
|
||||
arg2fixturedeflist = funcargs.FixtureRequest(item1)._arg2fixturedeflist
|
||||
assert len(arg2fixturedeflist) == 1
|
||||
assert arg2fixturedeflist[0].__name__ == "pytest_funcarg__something"
|
||||
|
||||
def test_getfuncargvalue_recursive(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
|
@ -669,7 +669,7 @@ class TestRequest:
|
|||
def test_func(something): pass
|
||||
""")
|
||||
req = item._request
|
||||
pytest.raises(FuncargLookupError, req.getfuncargvalue, "notexists")
|
||||
pytest.raises(FixtureLookupError, req.getfuncargvalue, "notexists")
|
||||
val = req.getfuncargvalue("something")
|
||||
assert val == 1
|
||||
val = req.getfuncargvalue("something")
|
||||
|
@ -717,7 +717,7 @@ class TestRequest:
|
|||
def test_request_getmodulepath(self, testdir):
|
||||
modcol = testdir.getmodulecol("def test_somefunc(): pass")
|
||||
item, = testdir.genitems([modcol])
|
||||
req = funcargs.FuncargRequest(item)
|
||||
req = funcargs.FixtureRequest(item)
|
||||
assert req.fspath == modcol.fspath
|
||||
|
||||
class TestMarking:
|
||||
|
@ -731,7 +731,7 @@ class TestMarking:
|
|||
def test_func2(self, something):
|
||||
pass
|
||||
""")
|
||||
req1 = funcargs.FuncargRequest(item1)
|
||||
req1 = funcargs.FixtureRequest(item1)
|
||||
assert 'xfail' not in item1.keywords
|
||||
req1.applymarker(pytest.mark.xfail)
|
||||
assert 'xfail' in item1.keywords
|
||||
|
@ -814,7 +814,7 @@ class TestRequestCachedSetup:
|
|||
|
||||
def test_request_cachedsetup_extrakey(self, testdir):
|
||||
item1 = testdir.getitem("def test_func(): pass")
|
||||
req1 = funcargs.FuncargRequest(item1)
|
||||
req1 = funcargs.FixtureRequest(item1)
|
||||
l = ["hello", "world"]
|
||||
def setup():
|
||||
return l.pop()
|
||||
|
@ -829,7 +829,7 @@ class TestRequestCachedSetup:
|
|||
|
||||
def test_request_cachedsetup_cache_deletion(self, testdir):
|
||||
item1 = testdir.getitem("def test_func(): pass")
|
||||
req1 = funcargs.FuncargRequest(item1)
|
||||
req1 = funcargs.FixtureRequest(item1)
|
||||
l = []
|
||||
def setup():
|
||||
l.append("setup")
|
||||
|
@ -906,14 +906,14 @@ class TestMetafunc:
|
|||
def test_no_funcargs(self, testdir):
|
||||
def function(): pass
|
||||
metafunc = funcargs.Metafunc(function)
|
||||
assert not metafunc.funcargnames
|
||||
assert not metafunc.fixturenames
|
||||
repr(metafunc._calls)
|
||||
|
||||
def test_function_basic(self):
|
||||
def func(arg1, arg2="qwe"): pass
|
||||
metafunc = funcargs.Metafunc(func)
|
||||
assert len(metafunc.funcargnames) == 1
|
||||
assert 'arg1' in metafunc.funcargnames
|
||||
assert len(metafunc.fixturenames) == 1
|
||||
assert 'arg1' in metafunc.fixturenames
|
||||
assert metafunc.function is func
|
||||
assert metafunc.cls is None
|
||||
|
||||
|
@ -1032,7 +1032,7 @@ class TestMetafunc:
|
|||
def test_parametrize_functional(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
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('y', [2])
|
||||
def pytest_funcarg__x(request):
|
||||
|
@ -1170,7 +1170,7 @@ class TestMetafuncFunctional:
|
|||
def test_addcall_with_two_funcargs_generators(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
def pytest_generate_tests(metafunc):
|
||||
assert "arg1" in metafunc.funcargnames
|
||||
assert "arg1" in metafunc.fixturenames
|
||||
metafunc.addcall(funcargs=dict(arg1=1, arg2=2))
|
||||
""")
|
||||
p = testdir.makepyfile("""
|
||||
|
@ -1213,7 +1213,7 @@ class TestMetafuncFunctional:
|
|||
def test_noself_in_method(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
def pytest_generate_tests(metafunc):
|
||||
assert 'xyz' not in metafunc.funcargnames
|
||||
assert 'xyz' not in metafunc.fixturenames
|
||||
|
||||
class TestHello:
|
||||
def test_hello(xyz):
|
||||
|
@ -1228,7 +1228,7 @@ class TestMetafuncFunctional:
|
|||
def test_generate_plugin_and_module(self, testdir):
|
||||
testdir.makeconftest("""
|
||||
def pytest_generate_tests(metafunc):
|
||||
assert "arg1" in metafunc.funcargnames
|
||||
assert "arg1" in metafunc.fixturenames
|
||||
metafunc.addcall(id="world", param=(2,100))
|
||||
""")
|
||||
p = testdir.makepyfile("""
|
||||
|
@ -1342,7 +1342,7 @@ class TestMetafuncFunctional:
|
|||
def test_parametrize_on_setup_arg(self, testdir):
|
||||
p = testdir.makepyfile("""
|
||||
def pytest_generate_tests(metafunc):
|
||||
assert "arg1" in metafunc.funcargnames
|
||||
assert "arg1" in metafunc.fixturenames
|
||||
metafunc.parametrize("arg1", [1], indirect=True)
|
||||
|
||||
def pytest_funcarg__arg1(request):
|
||||
|
@ -1403,7 +1403,7 @@ def test_funcarg_non_pycollectobj(testdir): # rough jstests usage
|
|||
clscol = rep.result[0]
|
||||
clscol.obj = lambda arg1: None
|
||||
clscol.funcargs = {}
|
||||
funcargs.fillfuncargs(clscol)
|
||||
funcargs.fillfixtures(clscol)
|
||||
assert clscol.funcargs['arg1'] == 42
|
||||
|
||||
|
||||
|
@ -1488,7 +1488,7 @@ class TestReportInfo:
|
|||
"""
|
||||
|
||||
def test_show_funcarg(testdir):
|
||||
result = testdir.runpytest("--funcargs")
|
||||
result = testdir.runpytest("--fixtures")
|
||||
result.stdout.fnmatch_lines([
|
||||
"*tmpdir*",
|
||||
"*temporary directory*",
|
||||
|
@ -1669,7 +1669,7 @@ def test_issue117_sessionscopeteardown(testdir):
|
|||
])
|
||||
|
||||
|
||||
class TestFuncargFactory:
|
||||
class TestFixtureFactory:
|
||||
def test_receives_funcargs(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -1809,7 +1809,7 @@ class TestResourceIntegrationFunctional:
|
|||
"*test_function*advanced*FAILED",
|
||||
])
|
||||
|
||||
class TestFuncargManager:
|
||||
class TestFixtureManager:
|
||||
def pytest_funcarg__testdir(self, request):
|
||||
testdir = request.getfuncargvalue("testdir")
|
||||
testdir.makeconftest("""
|
||||
|
@ -1817,7 +1817,7 @@ class TestFuncargManager:
|
|||
return "conftest"
|
||||
|
||||
def pytest_funcarg__fm(request):
|
||||
return request.funcargmanager
|
||||
return request._fixturemanager
|
||||
|
||||
def pytest_funcarg__item(request):
|
||||
return request._pyfuncitem
|
||||
|
@ -1828,7 +1828,7 @@ class TestFuncargManager:
|
|||
testdir.makepyfile("""
|
||||
def test_hello(item, fm):
|
||||
for name in ("fm", "hello", "item"):
|
||||
faclist = fm.getfactorylist(name, item.nodeid)
|
||||
faclist = fm.getfixturedeflist(name, item.nodeid)
|
||||
assert len(faclist) == 1
|
||||
fac = faclist[0]
|
||||
assert fac.func.__name__ == "pytest_funcarg__" + name
|
||||
|
@ -1844,7 +1844,7 @@ class TestFuncargManager:
|
|||
def pytest_funcarg__hello(self, request):
|
||||
return "class"
|
||||
def test_hello(self, item, fm):
|
||||
faclist = fm.getfactorylist("hello", item.nodeid)
|
||||
faclist = fm.getfixturedeflist("hello", item.nodeid)
|
||||
print (faclist)
|
||||
assert len(faclist) == 3
|
||||
assert faclist[0].func(item._request) == "conftest"
|
||||
|
@ -1870,7 +1870,7 @@ class TestSetupDiscovery:
|
|||
pass
|
||||
|
||||
def pytest_funcarg__fm(request):
|
||||
return request.funcargmanager
|
||||
return request._fixturemanager
|
||||
|
||||
def pytest_funcarg__item(request):
|
||||
return request._pyfuncitem
|
||||
|
@ -1919,11 +1919,11 @@ class TestSetupDiscovery:
|
|||
pass
|
||||
|
||||
def test_func1(request):
|
||||
assert "db" not in request.funcargnames
|
||||
assert "db" not in request.fixturenames
|
||||
|
||||
@pytest.mark.needsdb
|
||||
def test_func2(request):
|
||||
assert "db" in request.funcargnames
|
||||
assert "db" in request.fixturenames
|
||||
""")
|
||||
reprec = testdir.inline_run("-s")
|
||||
reprec.assertoutcome(passed=2)
|
||||
|
@ -2105,7 +2105,7 @@ class TestSetupManagement:
|
|||
reprec.assertoutcome(passed=5)
|
||||
|
||||
|
||||
class TestFuncargMarker:
|
||||
class TestFixtureMarker:
|
||||
def test_parametrize(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
|
@ -2686,7 +2686,7 @@ def test_setup_funcarg_order(testdir):
|
|||
reprec.assertoutcome(passed=1)
|
||||
|
||||
|
||||
def test_request_funcargnames(testdir):
|
||||
def test_request_fixturenames(testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
@pytest.fixture()
|
||||
|
@ -2699,8 +2699,23 @@ def test_request_funcargnames(testdir):
|
|||
def sarg(tmpdir):
|
||||
pass
|
||||
def test_function(request, farg):
|
||||
assert set(request.funcargnames) == \
|
||||
assert set(request.fixturenames) == \
|
||||
set(["tmpdir", "sarg", "arg1", "request", "farg"])
|
||||
""")
|
||||
reprec = testdir.inline_run()
|
||||
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)
|
||||
|
|
|
@ -26,7 +26,7 @@ class Option:
|
|||
return l
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if "option" in metafunc.funcargnames:
|
||||
if "option" in metafunc.fixturenames:
|
||||
metafunc.addcall(id="default",
|
||||
funcargs={'option': Option(verbose=False)})
|
||||
metafunc.addcall(id="verbose",
|
||||
|
|
Loading…
Reference in New Issue