Yield Fixtures for Cleanup
Fixtures that use yield instead of return can perform cleanup after the test finishes. Code after the yield statement runs as teardown.
Basic Yield Fixture
import pytest
import tempfile
import os
@pytest.fixture
def temp_file():
# Setup: create a temporary file
fd, path = tempfile.mkstemp()
yield path # Give the path to the test
# Teardown: clean up after the test
os.close(fd)
os.unlink(path)
def test_write_to_file(temp_file):
with open(temp_file, "w") as f:
f.write("hello")
with open(temp_file) as f:
assert f.read() == "hello"
# The temp file is automatically deleted after the test
Database Connection Cleanup
A common pattern is setting up and tearing down database connections:
@pytest.fixture
def db():
connection = create_db_connection()
connection.begin_transaction()
yield connection
# This runs even if the test fails
connection.rollback()
connection.close()
def test_insert_user(db):
db.execute("INSERT INTO users (name) VALUES ('Alice')")
result = db.execute("SELECT * FROM users")
assert len(result) == 1
# Transaction is rolled back, database stays clean
Yield with Exception Handling
Teardown code runs even if the test raises an exception:
@pytest.fixture
def resource():
res = acquire_resource()
try:
yield res
finally:
# This ALWAYS runs
res.release()
def test_with_resource(resource):
assert resource.is_ready()
# If this test crashes, resource.release() still runs