Code Reference

Testing with pytest

Python · Reference cheat sheet

Testing with pytest

Python · Reference cheat sheet


📋 Overview

pytest discovers and runs tests with plain assert, fixtures, parametrization, and rich failure diffs. Prefer it over unittest for new projects. Name files test_*.py or *_test.py.

🔧 Core concepts

FeatureRole
Discoverytest_* functions/classes
assertRewritten with introspection
FixturesSetup/teardown via @pytest.fixture
parametrizeData-driven cases
Markers@pytest.mark.skip, slow, etc.
raisesExpect exceptions
tmp_pathTemp directory fixture
Pluginspytest-cov, pytest-asyncio, …

Run with pytest or python -m pytest. Exit code 0 = all passed.

💡 Examples

Basic tests:

# test_mathutil.py
def add(a: int, b: int) -> int:
    return a + b

def test_add():
    assert add(2, 3) == 5

def test_add_negative():
    assert add(-1, 1) == 0

Fixtures and tmp_path:

import pytest
from pathlib import Path

@pytest.fixture
def sample_file(tmp_path: Path) -> Path:
    p = tmp_path / "data.txt"
    p.write_text("hello", encoding="utf-8")
    return p

def test_read(sample_file: Path):
    assert sample_file.read_text(encoding="utf-8") == "hello"

Parametrize and raises:

import pytest

@pytest.mark.parametrize("n,expected", [(0, 0), (1, 1), (2, 4)])
def test_square(n: int, expected: int):
    assert n * n == expected

def test_div_zero():
    with pytest.raises(ZeroDivisionError):
        _ = 1 / 0

CLI:

pytest -q
pytest -k "add" --maxfail=1
pytest --cov=mypkg --cov-report=term-missing

⚠️ Pitfalls

  • Tests that depend on execution order or shared global state flake.
  • Overusing mocks hides real integration bugs — mix unit + integration.
  • Mutable fixture state shared across tests when scope is wrong.
  • Asserting on exact error strings is brittle — match exception type.
  • Don't commit secrets into test fixtures.

On this page