🎓 Advanced · Topic 08
Testing & Debugging
Write automated tests with pytest, mock external dependencies, measure coverage, and use Python's debugging tools to squash bugs fast.
⏱ ~60 min
🔴 Advanced
✅ Quality
pytest Basics
pytest discovers tests automatically: any file named test_*.py and any function prefixed test_ is a test. No boilerplate classes required.
test_math.py
# The function under test
def divide(a: float, b: float) -> float:
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
# Tests
def test_divide_normal():
assert divide(10, 2) == 5.0
def test_divide_float():
assert divide(1, 3) == pytest.approx(0.333, rel=1e-2)
def test_divide_by_zero():
import pytest
with pytest.raises(ValueError, match="Cannot divide"):
divide(5, 0)
Terminal — running pytest
pytest # run all tests
pytest test_math.py -v # verbose output
pytest -k "divide" -v # filter by name
pytest --cov=. --cov-report=html # coverage report
Fixtures & Parametrize
Fixtures set up shared test state. @pytest.mark.parametrize runs one test with multiple input/output pairs.
conftest.py + test_user.py
import pytest
@pytest.fixture
def sample_user():
return {"name": "Alice", "age": 30}
def test_user_name(sample_user):
assert sample_user["name"] == "Alice"
@pytest.mark.parametrize("a,b,expected", [
(2, 3, 5),
(0, 0, 0),
(-1, 1, 0),
])
def test_add(a, b, expected):
assert a + b == expected # runs 3 times
Mocking with unittest.mock
Replace real dependencies (databases, APIs, the clock) with controlled fakes to make tests fast and deterministic.
test_api.py
from unittest.mock import patch, MagicMock
import requests
def get_username(user_id):
r = requests.get(f"https://api.example.com/users/{user_id}")
return r.json()["name"]
def test_get_username():
mock_resp = MagicMock()
mock_resp.json.return_value = {"name": "Alice"}
with patch("requests.get", return_value=mock_resp):
result = get_username(1)
assert result == "Alice" # no real HTTP call made
🐛 Debugging tip — use breakpoint() Drop breakpoint() anywhere in your code to launch the Python debugger (pdb). Type n to step, p var to inspect, c to continue, q to quit.