Testing in Python: pytest, mocks and coverage
You write fast, readable tests with pytest, isolate external dependencies with mocks, measure coverage and catch bugs with tests first.
Level 201 · 18 lessons · 18 practice labs
Lessons
pytest basics
- Why test? The limits of trying things by hand
- Your first test with pytest and assert
- Test discovery and project layout
- Expecting errors: pytest.raises
- Many cases in one test with parametrize
- Short task: test a password validator
Fixtures and mocks
- Fixtures: setup and teardown
- tmp_path and monkeypatch
- Mock objects with unittest.mock
- Faking HTTP requests and the clock
- Short task: test a function that calls an API, without a network
Quality and method
- Measuring coverage: pytest-cov
- Test-driven development: red, green, refactor
- Property-based testing: hypothesis
- doctest, markers and separating slow tests
- Writing a regression test for a security bug
- Short task: put a safety net under untested legacy code
Capstone
- Capstone: a small library with 90 percent coverage
Practice labs
- Writing the first test for a discount function: Write three pytest tests for a ready discount function covering the normal, boundary and zero-amount cases.
- Testing an expected error with pytest.raises: Test a function that must raise ValueError for a negative age with pytest.raises and match, checking the message too.
- Testing a tax calculation with parametrize: Collapse ten copy-pasted tax tests into one parametrize test and give each case a readable id.
- Exposing a hidden bug with a test: Write the test that catches the month-end bug in a date range function that seems to work, then fix the code.
- Writing a fixture for a temporary database: Write a yield fixture that gives each test a clean SQLite database and closes it afterwards.
- Testing code that depends on environment variables: Test a loader's cases with the variable set and unset by changing the environment variable with monkeypatch.
- Testing a notification without sending e-mail: Replace the mailer in a notification service with a Mock and assert it was called with the right recipient and subject.
- Testing clock-dependent code with a fixed time: Restructure code that computes expired coupons to take the clock from outside and test the midnight boundary.
- Finding and testing uncovered branches: Raise branch coverage above ninety percent by writing tests for the error branches pytest-cov shows as missing.
- Developing a slug function test-first: From a given requirement list write failing tests first, pass them with minimal code and refactor at the end.
- Pinning legacy pricing code with tests: Pin the current behaviour of an undocumented pricing function with characterisation tests, then simplify it without changing behaviour.
- Testing an encode-decode pair with hypothesis: Test the round-trip property of an encode and decode function pair with hypothesis.
- Stating the properties of a sort function: Write orderedness and element-preservation properties for a hand-written sort with hypothesis and fix the counterexample it finds.
- Marking and separating slow tests: Add a custom marker to slow tests, register it in pyproject.toml and make the default run skip them.
- A regression test for an authorisation bypass: Write a test reproducing the bug that lets a user view someone else's invoice, fix the code and show the test now passes.
- Organising shared fixtures by scope: Move set-up code copied across files into session- and function-scoped fixtures in conftest.py so the expensive set-up runs once while tests never see each other's data.
- Catching a reported bug with a test first: Write a test that fails with the input from a bug report, then fix the refund calculation; the test must be red before the fix and green after it.
- Testing a shopping cart with a stateful test: Compare a cart class against a simple model with hypothesis's rule-based state machine, study the smallest failing step sequence it finds and fix the bug.
About this course
You write fast, readable tests with pytest, isolate external dependencies with mocks, measure coverage and catch bugs with tests first.
What you will learn
- pytest basics
- Fixtures and mocks
- Quality and method
- Capstone
Prerequisites
Finishing the level 101 courses of the same path, or knowing those topics, is enough.
Lab environment
Lessons run in your own Kali Linux terminal that opens in the browser. Nothing to install; the lab starts clean in every lesson.
Frequently asked questions
- Is this course right for my level?
- The course is at level 201; it assumes you know the topics of the lower-level courses.
- Is there anything to install?
- No. Every lesson runs in your own lab environment that opens in the browser.
- How do lessons work?
- Each lesson has 8 to 10 steps and a short quiz. Early steps show the command to type, later steps give less help; if two attempts fail, the solution opens.
- Can I try it for free?
- Yes. The first three lessons of every course are free.