allow fixture functions to be implemented as context managers:

@pytest.fixture
def myfix():
    # setup
    yield 1
    # teardown
This commit is contained in:
holger krekel 2013-05-05 14:48:37 +02:00
parent 8e41ef5776
commit 56aa9962fc
5 changed files with 133 additions and 4 deletions

View File

@ -1,4 +1,12 @@
Changes between 2.3.4 and 2.3.5dev Changes between 2.3.5 and DEV
-----------------------------------
- (experimental) allow fixture functions to be
implemented as context managers
Changes between 2.3.4 and 2.3.5
----------------------------------- -----------------------------------
- never consider a fixture function for test function collection - never consider a fixture function for test function collection

View File

@ -1,2 +1,2 @@
# #
__version__ = '2.3.6.dev1' __version__ = '2.3.6.dev2'

View File

@ -1613,6 +1613,29 @@ class FixtureManager:
except ValueError: except ValueError:
pass pass
def call_fixture_func(fixturefunc, request, kwargs):
if is_generator(fixturefunc):
iter = fixturefunc(**kwargs)
next = getattr(iter, "__next__", None)
if next is None:
next = getattr(iter, "next")
res = next()
def teardown():
try:
next()
except StopIteration:
pass
else:
fs, lineno = getfslineno(fixturefunc)
location = "%s:%s" % (fs, lineno+1)
pytest.fail(
"fixture function %s has more than one 'yield': \n%s" %
(fixturefunc.__name__, location), pytrace=False)
request.addfinalizer(teardown)
else:
res = fixturefunc(**kwargs)
return res
class FixtureDef: class FixtureDef:
""" A container for a factory definition. """ """ A container for a factory definition. """
def __init__(self, fixturemanager, baseid, argname, func, scope, params, def __init__(self, fixturemanager, baseid, argname, func, scope, params,
@ -1663,7 +1686,7 @@ class FixtureDef:
fixturefunc = fixturefunc.__get__(request.instance) fixturefunc = fixturefunc.__get__(request.instance)
except AttributeError: except AttributeError:
pass pass
result = fixturefunc(**kwargs) result = call_fixture_func(fixturefunc, request, kwargs)
assert not hasattr(self, "cached_result") assert not hasattr(self, "cached_result")
self.cached_result = result self.cached_result = result
return result return result

View File

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

View File

@ -1795,3 +1795,101 @@ class TestShowFixtures:
*hello world* *hello world*
""") """)
class TestContextManagerFixtureFuncs:
def test_simple(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.fixture
def arg1():
print ("setup")
yield 1
print ("teardown")
def test_1(arg1):
print ("test1 %s" % arg1)
def test_2(arg1):
print ("test2 %s" % arg1)
assert 0
""")
result = testdir.runpytest("-s")
result.stdout.fnmatch_lines("""
setup
test1 1
teardown
setup
test2 1
teardown
""")
def test_scoped(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.fixture(scope="module")
def arg1():
print ("setup")
yield 1
print ("teardown")
def test_1(arg1):
print ("test1 %s" % arg1)
def test_2(arg1):
print ("test2 %s" % arg1)
""")
result = testdir.runpytest("-s")
result.stdout.fnmatch_lines("""
setup
test1 1
test2 1
teardown
""")
def test_setup_exception(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.fixture(scope="module")
def arg1():
pytest.fail("setup")
yield 1
def test_1(arg1):
pass
""")
result = testdir.runpytest("-s")
result.stdout.fnmatch_lines("""
*pytest.fail*setup*
*1 error*
""")
def test_teardown_exception(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.fixture(scope="module")
def arg1():
yield 1
pytest.fail("teardown")
def test_1(arg1):
pass
""")
result = testdir.runpytest("-s")
result.stdout.fnmatch_lines("""
*pytest.fail*teardown*
*1 passed*1 error*
""")
def test_yields_more_than_one(self, testdir):
testdir.makepyfile("""
import pytest
@pytest.fixture(scope="module")
def arg1():
yield 1
yield 2
def test_1(arg1):
pass
""")
result = testdir.runpytest("-s")
result.stdout.fnmatch_lines("""
*fixture function*
*test_yields*:2*
""")