@pytest.mark.parametrize runs the same test function multiple times with different inputs/expected values, giving true data-driven testing with one concise test and clear per-case reporting.
@pytest.mark.parametrize('email,valid', [('a@b.com', True), ('bad', False)]) def test_email(email, valid): assert is_valid(email) == valid runs the test once per tuple, each reported separately (so you see exactly which case failed). You can stack multiple parametrize decorators for a cartesian product, use ids= for readable case names, and combine with fixtures. This replaces copy-pasted near-duplicate tests and makes adding a new case a one-line change — ideal for validating boundary values, status codes, or many input permutations.
Validating login across many inputs: @pytest.mark.parametrize('user,pw,ok', [(valid), (empty), (wrong)]) exercises all paths in one test, and the report shows precisely which credential combo failed.
You have five nearly identical test functions differing only in input values. What's the pytest way to consolidate them?