Parameterized Testing with Pytest
Parameterization enables executing identical test logic with multiple input datasets, minimizing code duplication while maximizing coverage for similar test scenarios. Common use cases include validating payment processors, search algorithms, or mathematical functions.
The core mechanism stores test cases in collections and iterates through them, supplying distinct parameters during each test execution.
Implementation Techniques
Use @pytest.mark.parametrize decorator for parameterized tests. Consider a numerical addition function:
def calculate_sum(value1, value2):
return value1 + value2
List-Based Test Cases
Represent inputs as tuples within a list:
import pytest
def prepare_inputs():
return [
(3, 7, 10),
('foo', 'bar', 'foobar'),
(2.5, 3.5, 6.0),
((1,2), (3,4), (1,2,3,4))
]
@pytest.mark.parametrize('operand1, operand2, expected', prepare_inputs())
def test_calculate_sum(operand1, operand2, expected):
assert calculate_sum(operand1, operand2) == expected
Dictionary-Based Test Cases
Use named fields for improved readability:
import pytest
def get_test_scenarios():
return [
{'first': 3, 'second': 7, 'sum': 10},
{'first': 'foo', 'second': 'bar', 'sum': 'foobar'},
{'first': 2.5, 'second': 3.5, 'sum': 6.0}
]
@pytest.mark.parametrize('scenario', get_test_scenarios())
def test_calculate_sum(scenario):
assert calculate_sum(scenario['first'], scenario['second']) == scenario['sum']
Exteranl Data Sources
Load test cases from JSON files:
test_data.json
[
{"val_a": 3, "val_b": 7, "total": 10},
{"val_a": 2.5, "val_b": 3.5, "total": 6.0}
]
test_module.py
import pytest
import json
def read_external_data():
with open('test_data.json') as f:
return json.load(f)
@pytest.mark.parametrize('dataset', read_external_data())
def test_calculate_sum(dataset):
assert calculate_sum(dataset['val_a'], dataset['val_b']) == dataset['total']
Parameterization enhances test maintainability for data-driven validation scenarios.