strike keyword argument in favour of new pytest.yield_fixture decorator
This commit is contained in:
parent
431ce79d94
commit
086d4e4ced
|
@ -16,9 +16,12 @@ known incompatibilities:
|
|||
|
||||
new features:
|
||||
|
||||
- experimentally allow fixture functions to "yield" instead of "return"
|
||||
a fixture value, allowing direct integration with with-context managers
|
||||
in fixture functions and avoiding registration of finalization callbacks.
|
||||
- experimentally introduce a new pytest.yield_fixture decorator which
|
||||
has exactly the same parameters as pytest.fixture but expects
|
||||
a ``yield`` statement instead of a ``return statement`` from fixture functions.
|
||||
This allows direct integration with with-context managers
|
||||
in fixture functions and generally avoids registering of finalization callbacks
|
||||
in favour of treating the "after-yield" as teardown code.
|
||||
Thanks Andreas Pelme, Vladimir Keleshev, Floris Bruynooghe, Ronny Pfannschmidt
|
||||
and many others for discussions.
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ class FixtureFunctionMarker:
|
|||
return function
|
||||
|
||||
|
||||
def fixture(scope="function", params=None, autouse=False, yieldctx=False):
|
||||
def fixture(scope="function", params=None, autouse=False):
|
||||
""" (return a) decorator to mark a fixture factory function.
|
||||
|
||||
This decorator can be used (with or or without parameters) to define
|
||||
|
@ -62,16 +62,29 @@ def fixture(scope="function", params=None, autouse=False, yieldctx=False):
|
|||
can see it. If False (the default) then an explicit
|
||||
reference is needed to activate the fixture.
|
||||
|
||||
:arg yieldctx: if True, the fixture function yields a fixture value.
|
||||
Code after such a ``yield`` statement is treated as
|
||||
teardown code.
|
||||
"""
|
||||
if callable(scope) and params is None and autouse == False:
|
||||
# direct decoration
|
||||
return FixtureFunctionMarker(
|
||||
"function", params, autouse, yieldctx)(scope)
|
||||
"function", params, autouse)(scope)
|
||||
else:
|
||||
return FixtureFunctionMarker(scope, params, autouse, yieldctx)
|
||||
return FixtureFunctionMarker(scope, params, autouse)
|
||||
|
||||
def yield_fixture(scope="function", params=None, autouse=False):
|
||||
""" (return a) decorator to mark a yield-fixture factory function
|
||||
(EXPERIMENTAL).
|
||||
|
||||
This takes the same arguments as :py:func:`pytest.fixture` but
|
||||
expects a fixture function to use a ``yield`` instead of a ``return``
|
||||
statement to provide a fixture. See
|
||||
http://pytest.org/en/latest/yieldfixture.html for more info.
|
||||
"""
|
||||
if callable(scope) and params is None and autouse == False:
|
||||
# direct decoration
|
||||
return FixtureFunctionMarker(
|
||||
"function", params, autouse, yieldctx=True)(scope)
|
||||
else:
|
||||
return FixtureFunctionMarker(scope, params, autouse, yieldctx=True)
|
||||
|
||||
defaultfuncargprefixmarker = fixture()
|
||||
|
||||
|
@ -136,6 +149,7 @@ def pytest_namespace():
|
|||
raises.Exception = pytest.fail.Exception
|
||||
return {
|
||||
'fixture': fixture,
|
||||
'yield_fixture': yield_fixture,
|
||||
'raises' : raises,
|
||||
'collect': {
|
||||
'Module': Module, 'Class': Class, 'Instance': Instance,
|
||||
|
@ -1675,7 +1689,7 @@ def call_fixture_func(fixturefunc, request, kwargs, yieldctx):
|
|||
if yieldctx:
|
||||
if not is_generator(fixturefunc):
|
||||
fail_fixturefunc(fixturefunc,
|
||||
msg="yieldctx=True requires yield statement")
|
||||
msg="yield_fixture requires yield statement in function")
|
||||
iter = fixturefunc(**kwargs)
|
||||
next = getattr(iter, "__next__", None)
|
||||
if next is None:
|
||||
|
@ -1688,7 +1702,7 @@ def call_fixture_func(fixturefunc, request, kwargs, yieldctx):
|
|||
pass
|
||||
else:
|
||||
fail_fixturefunc(fixturefunc,
|
||||
"fixture function has more than one 'yield'")
|
||||
"yield_fixture function has more than one 'yield'")
|
||||
request.addfinalizer(teardown)
|
||||
else:
|
||||
res = fixturefunc(**kwargs)
|
||||
|
|
|
@ -276,8 +276,8 @@ module itself does not need to change or know about these details
|
|||
of fixture setup.
|
||||
|
||||
Note that pytest-2.4 introduced an experimental alternative
|
||||
:ref:`yield fixture mechanism <yieldctx>` for easier context manager integration
|
||||
and more linear writing of teardown code.
|
||||
:ref:`yield fixture mechanism <yieldfixture>` for easier context manager
|
||||
integration and more linear writing of teardown code.
|
||||
|
||||
.. _`request-context`:
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
.. _yieldctx:
|
||||
.. _yieldfixture:
|
||||
|
||||
Fixture functions using "yield" / context manager integration
|
||||
---------------------------------------------------------------
|
||||
|
@ -16,10 +16,9 @@ fully supporting all other fixture features.
|
|||
|
||||
"yielding" fixture values is an experimental feature and its exact
|
||||
declaration may change later but earliest in a 2.5 release. You can thus
|
||||
safely use this feature in the 2.4 series but may need to adapt your
|
||||
fixtures later. Test functions themselves will not need to change
|
||||
(they can be completely ignorant of the return/yield modes of
|
||||
fixture functions).
|
||||
safely use this feature in the 2.4 series but may need to adapt later.
|
||||
Test functions themselves will not need to change (as a general
|
||||
feature, they are ignorant of how fixtures are setup).
|
||||
|
||||
Let's look at a simple standalone-example using the new ``yield`` syntax::
|
||||
|
||||
|
@ -27,7 +26,7 @@ Let's look at a simple standalone-example using the new ``yield`` syntax::
|
|||
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(yieldctx=True)
|
||||
@pytest.yield_fixture
|
||||
def passwd():
|
||||
print ("\nsetup before yield")
|
||||
f = open("/etc/passwd")
|
||||
|
@ -62,7 +61,7 @@ Let's simplify the above ``passwd`` fixture::
|
|||
|
||||
import pytest
|
||||
|
||||
@pytest.fixture(yieldctx=True)
|
||||
@pytest.yield_fixture
|
||||
def passwd():
|
||||
with open("/etc/passwd") as f:
|
||||
yield f.readlines()
|
||||
|
|
|
@ -1980,7 +1980,7 @@ class TestContextManagerFixtureFuncs:
|
|||
def test_simple(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
@pytest.fixture(yieldctx=True)
|
||||
@pytest.yield_fixture
|
||||
def arg1():
|
||||
print ("setup")
|
||||
yield 1
|
||||
|
@ -2004,7 +2004,7 @@ class TestContextManagerFixtureFuncs:
|
|||
def test_scoped(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
@pytest.fixture(scope="module", yieldctx=True)
|
||||
@pytest.yield_fixture(scope="module")
|
||||
def arg1():
|
||||
print ("setup")
|
||||
yield 1
|
||||
|
@ -2025,7 +2025,7 @@ class TestContextManagerFixtureFuncs:
|
|||
def test_setup_exception(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
@pytest.fixture(scope="module", yieldctx=True)
|
||||
@pytest.yield_fixture(scope="module")
|
||||
def arg1():
|
||||
pytest.fail("setup")
|
||||
yield 1
|
||||
|
@ -2041,7 +2041,7 @@ class TestContextManagerFixtureFuncs:
|
|||
def test_teardown_exception(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
@pytest.fixture(scope="module", yieldctx=True)
|
||||
@pytest.yield_fixture(scope="module")
|
||||
def arg1():
|
||||
yield 1
|
||||
pytest.fail("teardown")
|
||||
|
@ -2057,7 +2057,7 @@ class TestContextManagerFixtureFuncs:
|
|||
def test_yields_more_than_one(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
@pytest.fixture(scope="module", yieldctx=True)
|
||||
@pytest.yield_fixture(scope="module")
|
||||
def arg1():
|
||||
yield 1
|
||||
yield 2
|
||||
|
@ -2074,7 +2074,7 @@ class TestContextManagerFixtureFuncs:
|
|||
def test_no_yield(self, testdir):
|
||||
testdir.makepyfile("""
|
||||
import pytest
|
||||
@pytest.fixture(scope="module", yieldctx=True)
|
||||
@pytest.yield_fixture(scope="module")
|
||||
def arg1():
|
||||
return 1
|
||||
def test_1(arg1):
|
||||
|
@ -2082,9 +2082,8 @@ class TestContextManagerFixtureFuncs:
|
|||
""")
|
||||
result = testdir.runpytest("-s")
|
||||
result.stdout.fnmatch_lines("""
|
||||
*yieldctx*requires*yield*
|
||||
*yieldctx=True*
|
||||
*yield_fixture*requires*yield*
|
||||
*yield_fixture*
|
||||
*def arg1*
|
||||
""")
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue