Module 08 / Project 01 — Parametrize¶
Learn Your Way¶
| Read | Build | Watch | Test | Review | Visualize | Try |
|---|---|---|---|---|---|---|
| — | This project | Walkthrough | — | Flashcards | — | — |
Focus¶
@pytest.mark.parametrizeto run one test function with many different inputs- Single-parameter and multi-parameter parametrize decorators
- The
idsparameter for readable test output - Testing utility functions with boundary values and edge cases
Why this project exists¶
Writing a separate test function for every input you want to check is tedious and creates a wall of nearly identical code. @pytest.mark.parametrize solves this by letting you define one test function and feed it a table of inputs and expected outputs. Pytest runs it once per row, reporting each as a separate test case. This is how professional codebases test functions that must handle many different inputs.
Run¶
Expected output¶
tests/test_utils.py::test_validate_email[valid-user@example.com] PASSED
tests/test_utils.py::test_validate_email[valid-name.tag@domain.org] PASSED
tests/test_utils.py::test_validate_email[invalid-missing-at] PASSED
tests/test_utils.py::test_validate_email[invalid-empty-string] PASSED
...
tests/test_utils.py::test_celsius_to_fahrenheit[freezing] PASSED
tests/test_utils.py::test_celsius_to_fahrenheit[boiling] PASSED
...
tests/test_utils.py::test_is_palindrome[racecar-True] PASSED
tests/test_utils.py::test_is_palindrome[hello-False] PASSED
...
tests/test_utils.py::test_clamp[below-minimum] PASSED
tests/test_utils.py::test_clamp[above-maximum] PASSED
...
Each parametrized case appears as a separate test with a readable name. All should pass.
Alter it¶
- Add three more email test cases to
test_validate_email: one with a+in the local part, one with multiple dots in the domain, and one with a missing domain. - Add a parametrize case for
celsius_to_fahrenheitusing absolute zero (-273.15 C = -459.67 F). - Add a new parametrized test for
clampwheremin_valequalsmax_val. What should happen when the range is a single point?
Break it¶
- Change one of the expected values in
test_celsius_to_fahrenheitto be wrong (e.g., change 32.0 to 33.0). Run the tests and read the failure output carefully — pytest shows you exactly which parametrize case failed and what the actual vs expected values were. - Remove the
idsparameter from one of the parametrize decorators and run with-v. Notice how the test names become less readable. - Add a duplicate test ID and see what pytest does.
Fix it¶
- Fix the broken expected value you changed above.
- Add the
idsback and verify the verbose output is readable again. - If any of your new test cases from "Alter it" fail, fix either the test or the function (decide which one is wrong first).
Explain it¶
- What is the difference between writing five separate test functions and one parametrized test with five cases?
- What does the
idsparameter do and why does it matter? - How does pytest report a failure in a parametrized test differently from a regular test?
- When would you use multi-parameter parametrize (multiple arguments) vs single-parameter?
Mastery check¶
You can move on when you can:
- Write a parametrized test from memory, without looking at examples.
- Explain what
idsdoes and why you should use it. - Add new test cases to an existing parametrized test in under a minute.
- Read pytest's parametrize failure output and understand which case failed and why.