Command Palette

Search for a command to run...

Hectal
Phase 11Intermediate12 of 18 in Python

Testing and Code Quality

Write tests with assert, pytest, mocks and doctest, measure coverage, lint and format with Ruff, and let pre-commit and CI check every change for you.

Code that runs is not the same as code that is right. This phase teaches the habit that separates hobby scripts from software people can depend on: write a small program that checks your program. You start with a plain assert, move to pytest (the tool almost every Python project uses), and learn fixtures, parametrised tests, and mocks and fakes for code that talks to the network, the clock or an AI model.

Then you look at the quality of the code itself. Ruff finds bugs and style problems and formats code in milliseconds, coverage shows which lines your tests never touched (and, just as important, what it cannot prove), and test-driven development and property-based testing give you two ways to find bugs you did not think of.

The phase ends by making all of it automatic: pre-commit hooks stop bad code before it is committed, and a GitHub Actions workflow runs the tests, the linter and the type checker on every push, on several Python versions. After this phase you can change code with confidence, which is the skill every later phase (and every real job) needs.

0/8 · 0%
8 topics ~4 h 30 code blocks & diagrams
Start with the first topic
1
11.1

Why Test, and What a Test Is

A test is a small program that runs your code with a chosen input and checks the result against the answer you expect. Tests are a safety net: they let you change code and find out in seconds whether something broke.

31 min 1 diagram 2 code practice

2
11.2

pytest: Writing and Running Tests

pytest finds functions named test_*, runs each one separately and reports the results. It rewrites your plain assert lines so a failure shows the actual values, which makes it the standard tool for Python tests.

28 min 1 diagram 2 code practice

3
11.3

Fixtures and Parametrised Tests

A fixture is a function that prepares what a test needs (data, a temporary folder, a fake client) and cleans up afterwards. @pytest.mark.parametrize runs the same test body with many inputs, so one test function becomes a whole table of cases.

31 min 1 diagram 2 code practice

4
11.4

Mocks, Fakes and Patching

A mock or fake is a stand-in for something slow, unsafe or unpredictable (the network, the clock, a database, an AI model), so a test checks only your own code. unittest.mock provides Mock, MagicMock and patch for this.

31 min 1 diagram 4 code practice

5
11.5

unittest and doctest

unittest is the testing framework built into Python: tests are methods of a TestCase class with setUp and assertEqual-style checks. doctest runs the examples written inside docstrings, so documentation that shows >>> sessions stays true.

30 min 1 diagram 4 code practice

6
11.6

Linting and Formatting with Ruff

Ruff is a very fast tool that checks Python code for likely bugs and style problems (ruff check) and rewrites its layout into one consistent style (ruff format). One tool replaces Flake8, isort, Black and several plugins.

30 min 1 diagram 2 code practice

7
11.7

Coverage, TDD and Property-Based Testing

Coverage shows which lines your tests never ran, test-driven development (red, green, refactor) writes the test before the code, and property-based testing lets a tool invent hundreds of inputs to break a rule you state. Together they find bugs your hand-picked examples miss.

33 min 1 diagram 4 code practice

8
11.8

Automating Quality: pre-commit and CI

Checks that depend on people remembering them get forgotten. A pre-commit hook runs formatting and linting before every commit, and a GitHub Actions workflow runs tests, lint and type checks on every push, on several Python versions, before code can merge.

30 min 1 diagram 2 code practice

Practise this phase

Hands-on exercises: write the code, run it, and press Check to have it tested automatically.