rename pytest.factory usages into pytest.fixture ones

This commit is contained in:
holger krekel 2012-10-05 10:21:35 +02:00
parent 439cc1238f
commit 9251e747af
8 changed files with 92 additions and 78 deletions

View File

@ -10,12 +10,12 @@ from py._code.code import TerminalRepr
import _pytest
cutdir = py.path.local(_pytest.__file__).dirpath()
class FactoryMarker:
class FixtureFunctionMarker:
def __init__(self, scope, params):
self.scope = scope
self.params = params
def __call__(self, function):
function._pytestfactory = self
function._pytestfixturefunction = self
return function
class SetupMarker:
@ -26,18 +26,32 @@ class SetupMarker:
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.
def fixture(scope=None, params=None):
""" return a decorator to mark a fixture factory function.
:arg scope: the scope for which this resource is shared, one of
The name of the fixture function can be referenced in a test context
to cause activation ahead of running tests. Test modules or classes
can use the pytest.mark.needsfixtures(fixturename) marker to specify
needed fixtures. Test functions can use fixture names as input arguments
in which case the object returned from the fixture function will be
injected.
:arg scope: the scope for which this fixture 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.
invocations of the fixture functions and their dependent
tests.
"""
return FactoryMarker(scope, params)
return FixtureFunctionMarker(scope, params)
def setup(scope="function"):
""" return a decorator to mark functions as setup functions.
""" 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".
@ -112,7 +126,7 @@ def pytest_sessionstart(session):
def pytest_namespace():
raises.Exception = pytest.fail.Exception
return {
'factory': factory,
'fixture': fixture,
'setup': setup,
'raises' : raises,
'collect': {
@ -1377,9 +1391,9 @@ class FuncargManager:
continue
# resource factories either have a pytest_funcarg__ prefix
# or are "funcarg" marked
marker = getattr(obj, "_pytestfactory", None)
marker = getattr(obj, "_pytestfixturefunction", None)
if marker is not None:
if not isinstance(marker, FactoryMarker):
if not isinstance(marker, FixtureFunctionMarker):
# magic globals with __getattr__
# give us something thats wrong for that case
continue

View File

@ -1,7 +1,7 @@
import pytest
@pytest.factory("session")
@pytest.fixture("session")
def setup(request):
setup = CostlySetup()
request.addfinalizer(setup.finalize)

View File

@ -5,12 +5,12 @@ serialization via the pickle module.
import py, pytest
pythonlist = ['python2.4', 'python2.5', 'python2.6', 'python2.7', 'python2.8']
@pytest.factory(params=pythonlist)
@pytest.fixture(params=pythonlist)
def python1(request, tmpdir):
picklefile = tmpdir.join("data.pickle")
return Python(request.param, picklefile)
@pytest.factory(params=pythonlist)
@pytest.fixture(params=pythonlist)
def python2(request, python1):
return Python(request.param, python1.picklefile)

View File

@ -125,7 +125,7 @@ the ``MYARG`` function argument.
.. note::
With pytest-2.3 you can use the :ref:`@pytest.factory` decorator
With pytest-2.3 you can use the :ref:`@pytest.fixture` decorator
to mark a function as a funcarg factory.
.. _`Convention over Configuration`: http://en.wikipedia.org/wiki/Convention_over_Configuration
@ -146,7 +146,7 @@ is not possible:
policy - in real-world examples some combinations
often should not run.
However, with pytest-2.3 you can use the :ref:`@pytest.factory` decorator
However, with pytest-2.3 you can use the :ref:`@pytest.fixture` decorator
and specify ``params`` so that all tests depending on the factory-created
resource will run multiple times with different parameters.

View File

@ -63,9 +63,9 @@ new facilities.
Direct scoping of funcarg factories
--------------------------------------------------------
Instead of calling cached_setup(), you can use the :ref:`@pytest.factory <@pytest.factory>` decorator and directly state the scope::
Instead of calling cached_setup(), you can use the :ref:`@pytest.fixture <@pytest.fixture>` decorator and directly state the scope::
@pytest.factory(scope="session")
@pytest.fixture(scope="session")
def db(request):
# factory will only be invoked once per session -
db = DataBase()
@ -87,7 +87,7 @@ or implement a ``pytest_generate_tests`` hook to perform
parametrization, i.e. calling a test multiple times with different value
sets. pytest-2.3 introduces a decorator for use on the factory itself::
@pytest.factory(params=["mysql", "pg"])
@pytest.fixture(params=["mysql", "pg"])
def db(request):
... # use request.param
@ -104,7 +104,7 @@ functions/classes were parametrized via
Of course it's perfectly fine to combine parametrization and scoping::
@pytest.factory(scope="session", params=["mysql", "pg"])
@pytest.fixture(scope="session", params=["mysql", "pg"])
def db(request):
if request.param == "mysql":
db = MySQL()
@ -125,7 +125,7 @@ When using the ``@factory`` decorator the name of the function
denotes the name under which the resource can be accessed as a function
argument::
@pytest.factory()
@pytest.fixture()
def db(request):
...

View File

@ -51,7 +51,7 @@ inputs lead to certain outputs.
Concretely, there are three main means of funcarg management:
* a `@pytest.factory`_ marker to define resource factories,
* a `@pytest.fixture`_ marker to define resource factories,
their scoping and parametrization. Factories can themselves
receive resources through their function arguments, easing
the setup of `interdependent resources`_. Factories can use
@ -77,9 +77,9 @@ be done with the classical xUnit style approach which encodes resource
setup statically into the test source code, leading to duplicate and
hard-to change fixtures.
.. _`@pytest.factory`:
.. _`@pytest.fixture`:
``@pytest.factory``: Creating parametrized, scoped resources
``@pytest.fixture``: Creating parametrized, scoped resources
=====================================================================
Basic funcarg injection example
@ -91,7 +91,7 @@ and a funcarg::
# content of ./test_simplefactory.py
import pytest
@pytest.factory()
@pytest.fixture()
def myfuncarg():
return 42
@ -99,7 +99,7 @@ and a funcarg::
assert myfuncarg == 17
Here, the ``test_function`` needs an object named ``myfuncarg`` and thus
py.test will discover and call the ``@pytest.factory`` marked ``myfuncarg``
py.test will discover and call the ``@pytest.fixture`` marked ``myfuncarg``
factory function. Running the tests looks like this::
$ py.test test_simplefactory.py
@ -168,7 +168,7 @@ funcarg factories starts at test classes, then test modules, then
Parametrizing test functions
==========================================================================
While the `@pytest.factory`_ decorator allows to define parametrization
While the `@pytest.fixture`_ decorator allows to define parametrization
of funcarg resources at the factory-level, there are also means to
define parametrization at test functions directly:
@ -365,18 +365,18 @@ the mechanism was extended and refined:
* previously funcarg factories were specified with a special
``pytest_funcarg__NAME`` prefix instead of using the
``@pytest.factory`` decorator.
``@pytest.fixture`` decorator.
* Factories received a `request`_ object which managed caching through
``request.cached_setup()`` calls and allowed using other funcargs via
``request.getfuncargvalue()`` calls. These intricate APIs made it hard
to do proper parametrization and implement resource caching. The
new ``@pytest.factory`` decorator allows to simply declare the scope
new ``@pytest.fixture`` decorator allows to simply declare the scope
and let pytest figure things out for you.
* 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.factory`_
and simplify your funcarg factory code to use the `@pytest.fixture`_
decorator instead. This will also allow to take advantage of
the `automatic per-resource grouping`_ of tests.

View File

@ -82,7 +82,7 @@ instances, based on a marker, you can do it using :ref:`pytest.mark`` and
import pytest
import unittest
@pytest.factory()
@pytest.fixture()
def db():
class DummyDB:
x = 1

View File

@ -744,7 +744,7 @@ class TestMarking:
def test_accessmarker_function(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.factory()
@pytest.fixture()
def markers(request):
return request.node.markers
@pytest.mark.XYZ
@ -758,7 +758,7 @@ class TestMarking:
def test_accessmarker_dynamic(self, testdir):
testdir.makeconftest("""
import pytest
@pytest.factory()
@pytest.fixture()
def markers(request):
return request.node.markers
@ -1674,11 +1674,11 @@ class TestFuncargFactory:
def test_receives_funcargs(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.factory()
@pytest.fixture()
def arg1():
return 1
@pytest.factory()
@pytest.fixture()
def arg2(arg1):
return arg1 + 1
@ -1694,11 +1694,11 @@ class TestFuncargFactory:
def test_receives_funcargs_scope_mismatch(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.factory(scope="function")
@pytest.fixture(scope="function")
def arg1():
return 1
@pytest.factory(scope="module")
@pytest.fixture(scope="module")
def arg2(arg1):
return arg1 + 1
@ -1717,12 +1717,12 @@ class TestFuncargFactory:
testdir.makepyfile("""
import pytest
l = []
@pytest.factory(params=[1,2])
@pytest.fixture(params=[1,2])
def arg1(request):
l.append(1)
return request.param
@pytest.factory()
@pytest.fixture()
def arg2(arg1):
return arg1 + 1
@ -1739,11 +1739,11 @@ class TestFuncargFactory:
testdir.makepyfile("""
import pytest
@pytest.factory()
@pytest.fixture()
def fail(missing):
return
@pytest.factory()
@pytest.fixture()
def call_fail(fail):
return
@ -1764,7 +1764,7 @@ class TestFuncargFactory:
class arg1:
def __init__(self, request):
self.x = 1
arg1 = pytest.factory()(arg1)
arg1 = pytest.fixture()(arg1)
class MySetup:
def __init__(self, request, arg1):
@ -1781,7 +1781,7 @@ class TestFuncargFactory:
def test_request_can_be_overridden(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.factory()
@pytest.fixture()
def request(request):
request.a = 1
return request
@ -1863,7 +1863,7 @@ class TestSetupDiscovery:
def perfunction(request, tmpdir):
pass
@pytest.factory()
@pytest.fixture()
def arg1(tmpdir):
pass
@pytest.setup()
@ -1918,7 +1918,7 @@ class TestSetupDiscovery:
def enabled(parentnode, markers):
return "needsdb" in markers
@pytest.factory(params=[1,2])
@pytest.fixture(params=[1,2])
def db(request):
return request.param
@ -1959,7 +1959,7 @@ class TestSetupManagement:
testdir.makepyfile("""
import pytest
l = []
@pytest.factory(scope="module")
@pytest.fixture(scope="module")
def arg():
l.append(1)
return 0
@ -1984,7 +1984,7 @@ class TestSetupManagement:
testdir.makepyfile("""
import pytest
l = []
@pytest.factory(params=[1,2])
@pytest.fixture(params=[1,2])
def arg(request):
return request.param
@ -2010,7 +2010,7 @@ class TestSetupManagement:
l = []
@pytest.factory(scope="session", params=[1,2])
@pytest.fixture(scope="session", params=[1,2])
def arg(request):
return request.param
@ -2036,11 +2036,11 @@ class TestSetupManagement:
l = []
@pytest.factory(scope="function", params=[1,2])
@pytest.fixture(scope="function", params=[1,2])
def farg(request):
return request.param
@pytest.factory(scope="class", params=list("ab"))
@pytest.fixture(scope="class", params=list("ab"))
def carg(request):
return request.param
@ -2117,7 +2117,7 @@ class TestFuncargMarker:
def test_parametrize(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.factory(params=["a", "b", "c"])
@pytest.fixture(params=["a", "b", "c"])
def arg(request):
return request.param
l = []
@ -2133,7 +2133,7 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
l = []
@pytest.factory(scope="module")
@pytest.fixture(scope="module")
def arg():
l.append(1)
return 1
@ -2155,7 +2155,7 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
l = []
@pytest.factory(scope="module")
@pytest.fixture(scope="module")
def arg():
l.append(1)
return 1
@ -2178,7 +2178,7 @@ class TestFuncargMarker:
import pytest
finalized = []
created = []
@pytest.factory(scope="module")
@pytest.fixture(scope="module")
def arg(request):
created.append(1)
assert request.scope == "module"
@ -2217,14 +2217,14 @@ class TestFuncargMarker:
import pytest
finalized = []
created = []
@pytest.factory(scope="function")
@pytest.fixture(scope="function")
def arg(request):
pass
""")
testdir.makepyfile(
test_mod1="""
import pytest
@pytest.factory(scope="session")
@pytest.fixture(scope="session")
def arg(request):
%s
def test_1(arg):
@ -2239,14 +2239,14 @@ class TestFuncargMarker:
def test_register_only_with_mark(self, testdir):
testdir.makeconftest("""
import pytest
@pytest.factory()
@pytest.fixture()
def arg():
return 1
""")
testdir.makepyfile(
test_mod1="""
import pytest
@pytest.factory()
@pytest.fixture()
def arg(arg):
return arg + 1
def test_1(arg):
@ -2258,7 +2258,7 @@ class TestFuncargMarker:
def test_parametrize_and_scope(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.factory(scope="module", params=["a", "b", "c"])
@pytest.fixture(scope="module", params=["a", "b", "c"])
def arg(request):
return request.param
l = []
@ -2276,13 +2276,13 @@ class TestFuncargMarker:
def test_scope_mismatch(self, testdir):
testdir.makeconftest("""
import pytest
@pytest.factory(scope="function")
@pytest.fixture(scope="function")
def arg(request):
pass
""")
testdir.makepyfile("""
import pytest
@pytest.factory(scope="session")
@pytest.fixture(scope="session")
def arg(arg):
pass
def test_mismatch(arg):
@ -2298,7 +2298,7 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
@pytest.factory(scope="module", params=[1, 2])
@pytest.fixture(scope="module", params=[1, 2])
def arg(request):
return request.param
@ -2317,10 +2317,10 @@ class TestFuncargMarker:
testdir.makeconftest("""
import pytest
@pytest.factory(scope="session", params="s1 s2".split())
@pytest.fixture(scope="session", params="s1 s2".split())
def sarg():
pass
@pytest.factory(scope="module", params="m1 m2".split())
@pytest.fixture(scope="module", params="m1 m2".split())
def marg():
pass
""")
@ -2365,11 +2365,11 @@ class TestFuncargMarker:
l = []
@pytest.factory(scope="function", params=[1,2])
@pytest.fixture(scope="function", params=[1,2])
def farg(request):
return request.param
@pytest.factory(scope="class", params=list("ab"))
@pytest.fixture(scope="class", params=list("ab"))
def carg(request):
return request.param
@ -2411,14 +2411,14 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
@pytest.factory(scope="function", params=[1, 2])
@pytest.fixture(scope="function", params=[1, 2])
def arg(request):
param = request.param
request.addfinalizer(lambda: l.append("fin:%s" % param))
l.append("create:%s" % param)
return request.param
@pytest.factory(scope="module", params=["mod1", "mod2"])
@pytest.fixture(scope="module", params=["mod1", "mod2"])
def modarg(request):
param = request.param
request.addfinalizer(lambda: l.append("fin:%s" % param))
@ -2455,7 +2455,7 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
@pytest.factory(scope="module", params=[1, 2])
@pytest.fixture(scope="module", params=[1, 2])
def arg(request):
request.config.l = l # to access from outer
x = request.param
@ -2484,7 +2484,7 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
@pytest.factory(scope="function", params=[1, 2])
@pytest.fixture(scope="function", params=[1, 2])
def arg(request):
x = request.param
request.addfinalizer(lambda: l.append("fin%s" % x))
@ -2506,7 +2506,7 @@ class TestFuncargMarker:
testdir.makepyfile("""
import pytest
@pytest.factory(scope="module", params=[1, 2])
@pytest.fixture(scope="module", params=[1, 2])
def arg(request):
return request.param
@ -2562,7 +2562,7 @@ class TestTestContextScopeAccess:
def test_funcarg(self, testdir, scope, ok, error):
testdir.makepyfile("""
import pytest
@pytest.factory(scope=%r)
@pytest.fixture(scope=%r)
def arg(request):
for x in %r:
assert hasattr(request, x)
@ -2582,7 +2582,7 @@ class TestErrors:
def test_subfactory_missing_funcarg(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.factory()
@pytest.fixture()
def gen(qwe123):
return 1
def test_something(gen):
@ -2618,7 +2618,7 @@ class TestTestContextVarious:
def test_newstyle_with_request(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.factory()
@pytest.fixture()
def arg(request):
pass
def test_1(arg):
@ -2630,7 +2630,7 @@ class TestTestContextVarious:
def test_setupcontext_no_param(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.factory(params=[1,2])
@pytest.fixture(params=[1,2])
def arg(request):
return request.param
@ -2683,7 +2683,7 @@ def test_setup_funcarg_order(testdir):
@pytest.setup()
def fix1():
l.append(1)
@pytest.factory()
@pytest.fixture()
def arg1():
l.append(2)
def test_hello(arg1):
@ -2696,10 +2696,10 @@ def test_setup_funcarg_order(testdir):
def test_request_funcargnames(testdir):
testdir.makepyfile("""
import pytest
@pytest.factory()
@pytest.fixture()
def arg1():
pass
@pytest.factory()
@pytest.fixture()
def farg(arg1):
pass
@pytest.setup()