Parametrized Tests
Scenario
You need to test an email validator with 10 different valid emails and 10 invalid ones. You copy-paste the test 20 times.
Mental model
Parametrization is a loop for your tests. Instead of writing one test per scenario, you write the test logic once and feed it a table of inputs and expected outputs.
Deep dive
Pytest's `@pytest.mark.parametrize` decorator allows you to define multiple sets of arguments for a single test function.
When pytest runs, it treats each parameter set as an independent, standalone test. If one input fails, the others will still run.
Code examples
Repetitive testing
def test_is_valid_email_1():
assert is_valid('test@example.com') is True
def test_is_valid_email_2():
assert is_valid('invalid') is False
This approach scales poorly as the number of test cases increases.
Parametrized test
import pytest
@pytest.mark.parametrize("email, expected", [
('test@example.com', True),
('invalid', False),
('user@sub.domain.com', True),
])
def test_is_valid_email(email, expected):
assert is_valid(email) == expected
The decorator unpacks each tuple into the test function arguments. Pytest reports this as 3 separate test cases.
Common mistakes
- Looping inside a test: If you write a `for` loop inside a single test, the test halts on the first failure, so you won't know if the remaining inputs in the loop would have passed.
Recall questions
- Why is `@pytest.mark.parametrize` better than a `for` loop inside a test?
- How do you specify the argument names for a parametrized test?
- Can you parametrize over fixtures?
Questions & answers
How would you test an API endpoint that filters by status, ensuring it works for 'active', 'pending', and 'archived'?
I would write a single test function that makes a request to the endpoint, decorated with `@pytest.mark.parametrize('status', ['active', 'pending', 'archived'])`.
What happens if we stack two `@pytest.mark.parametrize` decorators on a single test?
Pytest will generate the cartesian product (all combinations) of both parameter sets.
Continue learning
Previous: Pytest Basics and Fixtures