New in version 2.4.
pytest-2.4 allows fixture functions to seamlessly use a yield instead of a return statement to provide a fixture value while otherwise fully supporting all other fixture features.
Let’s look at a simple standalone-example using the yield syntax:
# content of test_yield.py
import pytest
@pytest.yield_fixture
def passwd():
print ("\nsetup before yield")
f = open("/etc/passwd")
yield f.readlines()
print ("teardown after yield")
f.close()
def test_has_lines(passwd):
print ("test called")
assert passwd
In contrast to finalization through registering callbacks, our fixture function used a yield statement to provide the lines of the /etc/passwd file. The code after the yield statement serves as the teardown code, avoiding the indirection of registering a teardown callback function.
Let’s run it with output capturing disabled:
$ py.test -q -s test_yield.py
setup before yield
test called
.teardown after yield
1 passed in 0.12 seconds
We can also seamlessly use the new syntax with with statements. Let’s simplify the above passwd fixture:
# content of test_yield2.py
import pytest
@pytest.yield_fixture
def passwd():
with open("/etc/passwd") as f:
yield f.readlines()
def test_has_lines(passwd):
assert len(passwd) >= 1
The file f will be closed after the test finished execution because the Python file object supports finalization when the with statement ends.
Note that the yield fixture form supports all other fixture features such as scope, params, etc., thus changing existing fixture functions to use yield is straightforward.
Note
While the yield syntax is similar to what contextlib.contextmanager() decorated functions provide, with pytest fixture functions the part after the “yield” will always be invoked, independently from the exception status of the test function which uses the fixture. This behaviour makes sense if you consider that many different test functions might use a module or session scoped fixture.
There are some topics that are worth mentioning:
If you want to feedback or participate in discussion of the above topics, please join our Contact channels, you are most welcome.