move pytest.mark.factory/setup to pytest.factory/setup, as per flub 's suggestion

This commit is contained in:
holger krekel 2012-08-02 12:41:46 +02:00
parent ae241a5071
commit 46dc7eeacb
8 changed files with 116 additions and 80 deletions

View File

@ -1,2 +1,2 @@
#
__version__ = '2.3.0.dev7'
__version__ = '2.3.0.dev8'

View File

@ -6,11 +6,45 @@ import pytest
from _pytest.main import getfslineno
from _pytest.monkeypatch import monkeypatch
from py._code.code import TerminalRepr
from _pytest.mark import MarkInfo
import _pytest
cutdir = py.path.local(_pytest.__file__).dirpath()
class FactoryMarker:
def __init__(self, scope, params):
self.scope = scope
self.params = params
def __call__(self, function):
function._pytestfactory = self
return function
class SetupMarker:
def __init__(self, scope):
self.scope = scope
def __call__(self, function):
function._pytestsetup = self
return function
# XXX a test fails when scope="function" how it should be, investigate
def factory(scope=None, params=None):
""" return a decorator to mark functions as resource factories.
:arg scope: the scope for which this resource is shared, one of
"function", "class", "module", "session". Defaults to "function".
:arg params: an optional list of parameters which will cause multiple
invocations of tests depending on the resource.
"""
return FactoryMarker(scope, params)
def setup(scope="function"):
""" return a decorator to mark functions as setup functions.
:arg scope: the scope for which the setup function will be active, one
of "function", "class", "module", "session".
Defaults to "function".
"""
return SetupMarker(scope)
def cached_property(f):
"""returns a cached property that is calculated by function f.
taken from http://code.activestate.com/recipes/576563-cached-property/"""
@ -78,6 +112,8 @@ def pytest_sessionstart(session):
def pytest_namespace():
raises.Exception = pytest.fail.Exception
return {
'factory': factory,
'setup': setup,
'raises' : raises,
'collect': {
'Module': Module, 'Class': Class, 'Instance': Instance,
@ -1251,12 +1287,12 @@ class FuncargManager:
# or are "funcarg" marked
if not callable(obj):
continue
marker = getattr(obj, "factory", None)
if marker is not None and isinstance(marker, MarkInfo):
marker = getattr(obj, "_pytestfactory", None)
if marker is not None:
assert not name.startswith(self._argprefix)
argname = name
scope = marker.kwargs.get("scope")
params = marker.kwargs.get("params")
scope = marker.scope
params = marker.params
new = True
elif name.startswith(self._argprefix):
argname = name[len(self._argprefix):]
@ -1265,9 +1301,9 @@ class FuncargManager:
new = False
else:
# no funcargs. check if we have a setup function.
setup = getattr(obj, "setup", None)
if setup is not None and isinstance(setup, MarkInfo):
scope = setup.kwargs.get("scope")
setup = getattr(obj, "_pytestsetup", None)
if setup is not None:
scope = setup.scope
sf = SetupCall(self, nodeid, obj, scope)
self.setuplist.append(sf)
continue

View File

@ -17,7 +17,7 @@
#
# The full version, including alpha/beta/rc tags.
# The short X.Y version.
version = release = "2.3.0.dev6"
version = release = "2.3.0.dev8"
import sys, os

View File

@ -209,7 +209,7 @@ during test execution and parametrization happens at collection time.
It follows that pytest_configure/session/runtest_setup are often not
appropriate for implementing common fixture needs. Therefore,
pytest-2.X introduces a new "@pytest.mark.setup" marker which takes
pytest-2.X introduces a new :ref:`@pytest.setup` marker which takes
an optional "scope" parameter.
See :ref:`new_setup` for examples.

View File

@ -43,7 +43,7 @@ instead of the default per-function scope.
Concretely, there are three means of resource and parametrization management:
* a `@pytest.mark.factory`_ marker to define resource factories,
* a `@pytest.factory`_ marker to define resource factories,
their scoping and parametrization. Factories can themselves
receive resources through their function arguments, easing
the setup of interdependent resources. They can also use
@ -62,16 +62,16 @@ you can use without defining them yourself. Moreover, third-party
plugins offer their own resources so that after installation
you can simply use them in your test and setup functions.
.. _`@pytest.mark.factory`:
.. _`@pytest.factory`:
``@pytest.mark.factory``: Creating parametrized, scoped resources
``@pytest.factory``: Creating parametrized, scoped resources
-----------------------------------------------------------------
.. regendoc:wipe
.. versionadded:: 2.3
The `@pytest.mark.factory`_ marker allows to
The `@pytest.factory`_ marker allows to
* mark a function as a factory for resources, useable by test and setup functions
* define parameters in order to run tests multiple times with different
@ -88,7 +88,7 @@ test session::
import pytest
import smtplib
@pytest.mark.factory(scope="session")
@pytest.factory(scope="session")
def smtp(testcontext):
smtp = smtplib.SMTP("merlinux.eu")
testcontext.addfinalizer(smtp.close)
@ -152,7 +152,7 @@ the ``smtp`` factory::
import pytest
import smtplib
@pytest.mark.factory(scope="session",
@pytest.factory(scope="session",
params=["merlinux.eu", "mail.python.org"])
def smtp(testcontext):
smtp = smtplib.SMTP(testcontext.param)
@ -256,7 +256,7 @@ object by sticking the ``smtp`` resource into it::
def __init__(self, smtp):
self.smtp = smtp
@pytest.mark.factory(scope="module")
@pytest.factory(scope="module")
def app(smtp):
return App(smtp)
@ -301,7 +301,7 @@ scoped on a per-module basis::
# content of test_module.py
import pytest
@pytest.mark.factory(scope="module", params=["mod1", "mod2"])
@pytest.factory(scope="module", params=["mod1", "mod2"])
def modarg(testcontext):
param = testcontext.param
print "create", param
@ -310,7 +310,7 @@ scoped on a per-module basis::
testcontext.addfinalizer(fin)
return param
@pytest.mark.factory(scope="function", params=[1,2])
@pytest.factory(scope="function", params=[1,2])
def otherarg(testcontext):
return testcontext.param
@ -363,14 +363,14 @@ resource was executed before the ``mod2`` resource was setup.
``testcontext``: interacting with test context
---------------------------------------------------
The ``testcontext`` object may be received by `@pytest.mark.factory`_ or
`@pytest.mark.setup`_ marked functions. It contains information relating
The ``testcontext`` object may be received by `@pytest.factory`_ or
`@pytest.setup`_ marked functions. It contains information relating
to the test context within which the function executes. Moreover, you
can call ``testcontext.addfinalizer(myfinalizer)`` in order to trigger
a call to ``myfinalizer`` after the last test in the test context has executed.
If passed to a parametrized factory ``testcontext.param`` will contain
a parameter (one value out of the ``params`` list specified with the
`@pytest.mark.factory`_ marker).
`@pytest.factory`_ marker).
.. autoclass:: _pytest.python.TestContext()
:members:

View File

@ -41,7 +41,7 @@ to mark functions as setup functions which:
All of these features are now demonstrated by little examples.
.. _`new_setup`:
.. _`@pytest.mark.setup`:
.. _`@pytest.setup`:
basic per-function setup
-------------------------------
@ -56,7 +56,7 @@ the test execute with this directory as current working dir::
import pytest
import os
@pytest.mark.setup()
@pytest.setup()
def mydir(tmpdir):
tmpdir.join("myfile").write("example content")
old = tmpdir.chdir()
@ -72,7 +72,7 @@ the test execute with this directory as current working dir::
assert not os.path.exists("anotherfile")
Our ``mydir`` setup function is executed on a per-function basis,
the default scope used by the ``pytest.mark.setup`` decorator.
the default scope used by the ``pytest.setup`` decorator.
It accesses the ``tmpdir`` resource which provides a new empty
directory path object. The ``test_function2`` here checks that
it executes with a fresh directory and specifically
@ -103,7 +103,7 @@ it into a ``conftest.py`` file into the root of your project::
import pytest
import os
@pytest.mark.setup()
@pytest.setup()
def cleandir(tmpdir):
old = tmpdir.chdir()
@ -118,7 +118,7 @@ test modules accessing a global resource
If you want test modules to access a global resource,
you can stick the resource to the module globals in
a per-module setup function. We use a :ref:`resource factory
<@pytest.mark.factory>` to create our global resource::
<@pytest.factory>` to create our global resource::
# content of conftest.py
import pytest
@ -127,11 +127,11 @@ a per-module setup function. We use a :ref:`resource factory
def __init__(self):
pass
@pytest.mark.factory(scope="session")
@pytest.factory(scope="session")
def globresource():
return GlobalResource()
@pytest.mark.setup(scope="module")
@pytest.setup(scope="module")
def setresource(testcontext, globresource):
testcontext.module.globresource = globresource
@ -169,7 +169,7 @@ factory and also add a finalizer::
def __init__(self, param):
self.param = param
@pytest.mark.factory(scope="session", params=[1,2])
@pytest.factory(scope="session", params=[1,2])
def globresource(testcontext):
g = GlobalResource(testcontext.param)
def fin():
@ -177,7 +177,7 @@ factory and also add a finalizer::
testcontext.addfinalizer(fin)
return g
@pytest.mark.setup(scope="module")
@pytest.setup(scope="module")
def setresource(testcontext, globresource):
testcontext.module.globresource = globresource

View File

@ -24,7 +24,7 @@ def main():
name='pytest',
description='py.test: simple powerful testing with Python',
long_description = long_description,
version='2.3.0.dev7',
version='2.3.0.dev8',
url='http://pytest.org',
license='MIT license',
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],

View File

@ -1581,7 +1581,7 @@ class TestRequestAPI:
result = testdir.makeconftest("""
import pytest
@pytest.mark.setup
@pytest.setup()
def mysetup(testcontext):
testcontext.uses_funcarg("db")
""")
@ -1595,11 +1595,11 @@ class TestFuncargFactory:
def test_receives_funcargs(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.mark.factory
@pytest.factory()
def arg1():
return 1
@pytest.mark.factory
@pytest.factory()
def arg2(arg1):
return arg1 + 1
@ -1615,11 +1615,11 @@ class TestFuncargFactory:
def test_receives_funcargs_scope_mismatch(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.mark.factory(scope="function")
@pytest.factory(scope="function")
def arg1():
return 1
@pytest.mark.factory(scope="module")
@pytest.factory(scope="module")
def arg2(arg1):
return arg1 + 1
@ -1638,12 +1638,12 @@ class TestFuncargFactory:
testdir.makepyfile("""
import pytest
l = []
@pytest.mark.factory(params=[1,2])
@pytest.factory(params=[1,2])
def arg1(testcontext):
l.append(1)
return testcontext.param
@pytest.mark.factory
@pytest.factory()
def arg2(arg1):
return arg1 + 1
@ -1725,14 +1725,14 @@ class TestSetupDiscovery:
testdir = request.getfuncargvalue("testdir")
testdir.makeconftest("""
import pytest
@pytest.mark.setup
@pytest.setup()
def perfunction(testcontext, tmpdir):
pass
@pytest.mark.factory
@pytest.factory()
def arg1(tmpdir):
pass
@pytest.mark.setup
@pytest.setup()
def perfunction2(arg1):
pass
@ -1767,11 +1767,11 @@ class TestSetupManagement:
testdir.makepyfile("""
import pytest
l = []
@pytest.mark.factory(scope="module")
@pytest.factory(scope="module")
def arg():
l.append(1)
return 0
@pytest.mark.setup(scope="class")
@pytest.setup(scope="class")
def something(arg):
l.append(2)
@ -1792,11 +1792,11 @@ class TestSetupManagement:
testdir.makepyfile("""
import pytest
l = []
@pytest.mark.factory(params=[1,2])
@pytest.factory(params=[1,2])
def arg(testcontext):
return testcontext.param
@pytest.mark.setup
@pytest.setup()
def something(arg):
l.append(arg)
@ -1818,11 +1818,11 @@ class TestSetupManagement:
l = []
@pytest.mark.factory(scope="session", params=[1,2])
@pytest.factory(scope="session", params=[1,2])
def arg(testcontext):
return testcontext.param
@pytest.mark.setup(scope="function")
@pytest.setup(scope="function")
def append(testcontext, arg):
if testcontext.function.__name__ == "test_some":
l.append(arg)
@ -1844,15 +1844,15 @@ class TestSetupManagement:
l = []
@pytest.mark.factory(scope="function", params=[1,2])
@pytest.factory(scope="function", params=[1,2])
def farg(testcontext):
return testcontext.param
@pytest.mark.factory(scope="class", params=list("ab"))
@pytest.factory(scope="class", params=list("ab"))
def carg(testcontext):
return testcontext.param
@pytest.mark.setup(scope="class")
@pytest.setup(scope="class")
def append(testcontext, farg, carg):
def fin():
l.append("fin_%s%s" % (carg, farg))
@ -1878,7 +1878,7 @@ class TestFuncargMarker:
def test_parametrize(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.mark.factory(params=["a", "b", "c"])
@pytest.factory(params=["a", "b", "c"])
def arg(testcontext):
return testcontext.param
l = []
@ -1894,7 +1894,7 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
l = []
@pytest.mark.factory(scope="module")
@pytest.factory(scope="module")
def arg():
l.append(1)
return 1
@ -1916,7 +1916,7 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
l = []
@pytest.mark.factory(scope="module")
@pytest.factory(scope="module")
def arg():
l.append(1)
return 1
@ -1939,7 +1939,7 @@ class TestFuncargMarker:
import pytest
finalized = []
created = []
@pytest.mark.factory(scope="module")
@pytest.factory(scope="module")
def arg(testcontext):
created.append(1)
assert testcontext.scope == "module"
@ -1978,14 +1978,14 @@ class TestFuncargMarker:
import pytest
finalized = []
created = []
@pytest.mark.factory(scope="function")
@pytest.factory(scope="function")
def arg(testcontext):
pass
""")
testdir.makepyfile(
test_mod1="""
import pytest
@pytest.mark.factory(scope="session")
@pytest.factory(scope="session")
def arg(testcontext):
%s
def test_1(arg):
@ -2000,14 +2000,14 @@ class TestFuncargMarker:
def test_register_only_with_mark(self, testdir):
testdir.makeconftest("""
import pytest
@pytest.mark.factory
@pytest.factory()
def arg():
return 1
""")
testdir.makepyfile(
test_mod1="""
import pytest
@pytest.mark.factory
@pytest.factory()
def arg(arg):
return arg + 1
def test_1(arg):
@ -2019,7 +2019,7 @@ class TestFuncargMarker:
def test_parametrize_and_scope(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.mark.factory(scope="module", params=["a", "b", "c"])
@pytest.factory(scope="module", params=["a", "b", "c"])
def arg(testcontext):
return testcontext.param
l = []
@ -2037,13 +2037,13 @@ class TestFuncargMarker:
def test_scope_mismatch(self, testdir):
testdir.makeconftest("""
import pytest
@pytest.mark.factory(scope="function")
@pytest.factory(scope="function")
def arg(testcontext):
pass
""")
testdir.makepyfile("""
import pytest
@pytest.mark.factory(scope="session")
@pytest.factory(scope="session")
def arg(arg):
pass
def test_mismatch(arg):
@ -2059,7 +2059,7 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
@pytest.mark.factory(scope="module", params=[1, 2])
@pytest.factory(scope="module", params=[1, 2])
def arg(testcontext):
return testcontext.param
@ -2078,10 +2078,10 @@ class TestFuncargMarker:
testdir.makeconftest("""
import pytest
@pytest.mark.factory(scope="session", params="s1 s2".split())
@pytest.factory(scope="session", params="s1 s2".split())
def sarg():
pass
@pytest.mark.factory(scope="module", params="m1 m2".split())
@pytest.factory(scope="module", params="m1 m2".split())
def marg():
pass
""")
@ -2126,15 +2126,15 @@ class TestFuncargMarker:
l = []
@pytest.mark.factory(scope="function", params=[1,2])
@pytest.factory(scope="function", params=[1,2])
def farg(testcontext):
return testcontext.param
@pytest.mark.factory(scope="class", params=list("ab"))
@pytest.factory(scope="class", params=list("ab"))
def carg(testcontext):
return testcontext.param
@pytest.mark.setup(scope="class")
@pytest.setup(scope="class")
def append(testcontext, farg, carg):
def fin():
l.append("fin_%s%s" % (carg, farg))
@ -2172,14 +2172,14 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
@pytest.mark.factory(scope="function", params=[1, 2])
@pytest.factory(scope="function", params=[1, 2])
def arg(testcontext):
param = testcontext.param
testcontext.addfinalizer(lambda: l.append("fin:%s" % param))
l.append("create:%s" % param)
return testcontext.param
@pytest.mark.factory(scope="module", params=["mod1", "mod2"])
@pytest.factory(scope="module", params=["mod1", "mod2"])
def modarg(testcontext):
param = testcontext.param
testcontext.addfinalizer(lambda: l.append("fin:%s" % param))
@ -2216,7 +2216,7 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
@pytest.mark.factory(scope="module", params=[1, 2])
@pytest.factory(scope="module", params=[1, 2])
def arg(testcontext):
testcontext.config.l = l # to access from outer
x = testcontext.param
@ -2245,7 +2245,7 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
@pytest.mark.factory(scope="function", params=[1, 2])
@pytest.factory(scope="function", params=[1, 2])
def arg(testcontext):
x = testcontext.param
testcontext.addfinalizer(lambda: l.append("fin%s" % x))
@ -2267,11 +2267,11 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
@pytest.mark.factory(scope="module", params=[1, 2])
@pytest.factory(scope="module", params=[1, 2])
def arg(testcontext):
return testcontext.param
@pytest.mark.setup(scope="module")
@pytest.setup(scope="module")
def mysetup(testcontext, arg):
testcontext.addfinalizer(lambda: l.append("fin%s" % arg))
l.append("setup%s" % arg)
@ -2304,7 +2304,7 @@ class TestTestContextScopeAccess:
def test_setup(self, testdir, scope, ok, error):
testdir.makepyfile("""
import pytest
@pytest.mark.setup(scope=%r)
@pytest.setup(scope=%r)
def myscoped(testcontext):
for x in %r:
assert hasattr(testcontext, x)
@ -2322,7 +2322,7 @@ class TestTestContextScopeAccess:
def test_resource(self, testdir, scope, ok, error):
testdir.makepyfile("""
import pytest
@pytest.mark.factory(scope=%r)
@pytest.factory(scope=%r)
def arg(testcontext):
for x in %r:
assert hasattr(testcontext, x)
@ -2341,7 +2341,7 @@ class TestTestContextVarious:
def test_newstyle_no_request(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.mark.factory
@pytest.factory()
def arg(request):
pass
def test_1(arg):
@ -2355,11 +2355,11 @@ class TestTestContextVarious:
def test_setupcontext_no_param(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.mark.factory(params=[1,2])
@pytest.factory(params=[1,2])
def arg(testcontext):
return testcontext.param
@pytest.mark.setup
@pytest.setup()
def mysetup(testcontext, arg):
assert not hasattr(testcontext, "param")
def test_1(arg):