Parameterized Fixtures
Sometimes you want to run the same test with different inputs. Parameterized fixtures let you provide multiple sets of data using the params argument.
Basic Parameterization
import pytest
@pytest.fixture(params=[1, 2, 3, 4, 5])
def number(request):
return request.param
def test_is_positive(number):
assert number > 0
# This test runs 5 times, once for each parameter
# test_is_positive[1], test_is_positive[2], etc.
Multiple Parameter Sets
You can parameterize with complex data structures:
@pytest.fixture(params=[
{"input": "hello", "expected": "HELLO"},
{"input": "world", "expected": "WORLD"},
{"input": "", "expected": ""},
])
def string_data(request):
return request.param
def test_upper(string_data):
assert string_data["input"].upper() == string_data["expected"]
Named Parameters with IDs
Use the ids argument to give readable names to each parameter set:
@pytest.fixture(
params=[0, 1, -1, 100],
ids=["zero", "positive", "negative", "large"]
)
def number(request):
return request.param
def test_abs(number):
assert abs(number) >= 0
# Output: test_abs[zero], test_abs[positive], test_abs[negative], test_abs[large]
Combining Fixtures
Parameterized fixtures can depend on other fixtures:
@pytest.fixture(params=["sqlite", "postgres"])
def db_engine(request):
return create_engine(request.param)
@pytest.fixture
def database(db_engine):
conn = db_engine.connect()
yield conn
conn.close()
def test_query(database):
result = database.execute("SELECT 1")
assert result.fetchone()
The database fixture runs once for each db_engine parameter.