allow factory/setup-markers on classes, using their respective __init__ methods which can use the funcarg mechanism

This commit is contained in:
holger krekel 2012-09-18 14:00:47 +02:00
parent a5e7e441d3
commit 6cb3281ddd
3 changed files with 38 additions and 14 deletions

View File

@ -1507,9 +1507,12 @@ class FactoryDef:
def getfuncargnames(function, startindex=None):
# XXX merge with main.py's varnames
argnames = py.std.inspect.getargs(py.code.getrawcode(function))[0]
if startindex is None:
startindex = py.std.inspect.ismethod(function) and 1 or 0
if inspect.isclass(function):
function = function.__init__
startindex = 1
elif startindex is None:
startindex = inspect.ismethod(function) and 1 or 0
argnames = inspect.getargs(py.code.getrawcode(function))[0]
defaults = getattr(function, 'func_defaults',
getattr(function, '__defaults__', None)) or ()
numdefaults = len(defaults)

View File

@ -389,19 +389,16 @@ object ``app`` and stick the ``smtp`` resource into it like this::
import pytest
class App:
@pytest.factory(scope="module")
class app:
def __init__(self, smtp):
self.smtp = smtp
@pytest.factory(scope="module")
def app(smtp):
return App(smtp)
def test_exists(app):
assert app.smtp
Here we define the factory local to the test module and make it access
the ``smtp`` resource by listing it as an input parameter. Let's run this::
Here we declare an ``app`` class to be a factory and have its init-method
use the previously defined ``smtp`` resource. Let's run it::
$ py.test -v test_appsetup.py
=========================== test session starts ============================
@ -418,7 +415,7 @@ the ``smtp`` resource by listing it as an input parameter. Let's run this::
Due to the parametrization of ``smtp`` the test will run twice with two
different ``App`` instances and respective smtp servers. There is no
need for the ``app`` factory to be aware of the parametrization. Note
that the ``app`` factory has a scope of ``module`` whereas it uses the
that the ``app`` factory has a scope of ``module`` but uses the
session-scoped ``smtp`` object: it is fine for factories to use
"broader" scoped resources but not the other way round. A
session-scoped resource could not use a module-scoped resource in a
@ -498,8 +495,8 @@ Let's run the tests in verbose mode and with looking at the print-output::
fin mod2
You can see that the parametrized module-scoped ``modarg`` resource caused
a re-ordering of test execution. The finalizer for the ``mod1`` parametrized
resource was executed before the ``mod2`` resource was setup.
an ordering of test execution that lead to the fewest possible "active" resources. The finalizer for the ``mod1`` parametrized resource was executed
before the ``mod2`` resource was setup.
.. currentmodule:: _pytest.python
.. _`request`:
@ -520,7 +517,6 @@ The ``request`` object may be received by `@pytest.factory`_ or
* to add finalizers/teardowns to be invoked when the last
test of the requesting test context executes
.. autoclass:: _pytest.python.FuncargRequest()
:members:

View File

@ -535,6 +535,11 @@ def test_getfuncargnames():
if sys.version_info < (3,0):
assert funcargs.getfuncargnames(A.f) == ['arg1']
class A:
def __init__(self, x):
pass
assert funcargs.getfuncargnames(A) == ["x"]
class TestFillFuncArgs:
def test_fillfuncargs_exposed(self):
# used by oejskit
@ -1727,6 +1732,26 @@ class TestFuncargFactory:
])
def test_factory_setup_as_classes(self, testdir):
testdir.makepyfile("""
import pytest
class arg1:
def __init__(self, request):
self.x = 1
arg1 = pytest.factory()(arg1)
class MySetup:
def __init__(self, request, arg1):
request.instance.arg1 = arg1
pytest.setup()(MySetup)
class TestClass:
def test_method(self):
assert self.arg1.x == 1
""")
reprec = testdir.inline_run()
reprec.assertoutcome(passed=1)
class TestResourceIntegrationFunctional:
def test_parametrize_with_ids(self, testdir):