Testing from zero to advancedFree

Pytest

From a first assert to fixtures, parametrize, mocking, coverage and writing your own plugin — the whole road to testing Python code. Six steps and a ten-question quiz in every chapter.

The six steps in every chapter

  1. 1Encounter
  2. 2Understand
  3. 3Worked
  4. 4Predict
  5. 5Apply
  6. 6Stretch
  1. 00Before you write a test — what you actually needThe thinking that comes before any test code: turning a vague requirement into a precise contract, making code testable, choosing cases with boundaries, knowing the expected answer without running the code, and deciding what not to test — all with plain Python and assert.50 min10 questions
  2. 01Installing pytest and your first testWhy checking by hand stops working, why a bare assert tells you almost nothing, and how to install pytest and write and run a first test file. Including the dots, the summary line, -q, -v and exit codes.40 min10 questions
  3. 02assert and reading failure reportsHow pytest sees inside a plain assert, how to read a failure report line by line, and which comparison to write so the report tells you the most.45 min10 questions
  4. 03Discovery and running tests — what pytest runs, and how to chooseWhich files, functions and classes pytest treats as tests, importing your code from a src/ and tests/ layout, node IDs, and running exactly what you need with -k, -x, --lf, --ff and --co.45 min10 questions
  5. 04Testing exceptions — pytest.raisesErrors are behaviour, so they need tests too. pytest.raises, DID NOT RAISE, subclass matching, why match= is a regex, inspecting the caught error with excinfo, and why only the last line belongs inside the with block.45 min10 questions
  6. 05Floats and pytest.approx — testing "close enough"Why 0.1 + 0.2 == 0.3 is false, what pytest.approx tolerates by default, when you need rel and abs, and why money wants Decimal rather than approx. With NaN, unordered results and timestamps.35 min10 questions
  7. 06parametrize — one test, many casesReplacing copy-pasted tests and loops inside a test with @pytest.mark.parametrize. Test IDs, ids= and pytest.param, stacking decorators, values and errors in one table, and the common mistakes.45 min10 questions
  8. 07Fixtures — setup written onceStop repeating setup: write it once with @pytest.fixture, request it by name, get a fresh copy in every test, and clean up with yield even when a test fails.45 min10 questions
  9. 08Fixture scope and conftest.py — sharing setup safelyBuild slow setup once and share it: the five scopes, --setup-show, the danger of shared state and ScopeMismatch, conftest.py for fixtures without imports and per-directory overrides, what autouse costs, and the order fixtures are created in.50 min10 questions
  10. 09Built-in fixtures — tmp_path, capsys and caplogThe fixtures pytest ships for the awkward parts of testing: files, printed output and logs. Test code that writes CSV and JSON without touching real paths, and check what it prints and logs.45 min10 questions
  11. 10monkeypatch — controlling the environment, time and the networkTesting code that depends on environment variables, the clock, randomness or the network. setenv, delenv, setattr, setitem, chdir, the automatic undo after every test, the "patch where it is looked up" rule, and dependency injection that needs no patching at all.50 min10 questions
  12. 11Mocking — checking how an external service was calledStand a Mock in for a payment or email client and check how it was called. return_value, side_effect, autospec, patch, mocker — and when a fake beats a mock.50 min10 questions
  13. 12Markers, skip and xfail — which tests run whereTell pytest what each test needs and what you expect of it with skip, skipif, importorskip and xfail; what strict=True, raises= and XPASS mean; register your own markers and select with -m; plus parametrized and factory fixtures.50 min10 questions
  14. 13Configuration and warnings — the rules in one fileStop typing the same flags on every run: put the project's rules in pyproject.toml or pytest.ini — testpaths, addopts, pythonpath, markers, xfail_strict, log_cli — and test and control warnings with pytest.warns, deprecated_call and filterwarnings.55 min10 questions
  15. 14Coverage and CI — which lines did your tests never run?Measuring coverage with pytest-cov, reading the Missing column, branch coverage, enforcing a minimum, running tests in parallel with pytest-xdist, and running the whole suite on every push with GitHub Actions. And why 100% coverage does not mean correct code.50 min10 questions
  16. 15Async tests, hooks and writing a pluginTesting async code with pytest-asyncio, then extending pytest with hooks in conftest.py — a --runslow flag, a marker, a report header — and finally turning that into a plugin of your own and testing it with pytester.60 min10 questions
  17. 16Test design and TDD — what makes a good testPlanning a test before writing it, Arrange-Act-Assert, testing behaviour rather than implementation, red-green-refactor, property-based testing with Hypothesis, the causes and cures of flaky tests, and a regression test for every bug.60 min10 questions