Lesson 54 of 55 · Python
Testing with pytest
Duration: 20 minutes
Testing with pytest
While unittest is built into the std‑lib, pytest has become the de‑facto standard for Python testing because of its simple syntax, powerful fixtures, and expressive assertions.
1️⃣ Install pytest
pip install pytest
2️⃣ A basic test file (test_math.py)
# test_math.py
def add(a, b):
return a + b
def mul(a, b):
return a * b
def test_add():
assert add(2, 3) == 5
assert add(-1, 1) == 0
def test_mul():
assert mul(3, 4) == 12
assert mul(0, 5) == 0
Run it with:
pytest -q
You’ll see a concise output showing which tests passed.
3️⃣ Fixtures – reusable setup/teardown
import pytest
@pytest.fixture
def sample_list():
return [1, 2, 3]
def test_append(sample_list):
sample_list.append(4)
assert sample_list == [1, 2, 3, 4]
Fixtures can also be autouse, scope‑session, scope‑module, etc.
4️⃣ Parametrized Tests – data‑driven testing
@pytest.mark.parametrize("a,b,expected", [
(1, 2, 3),
(5, 5, 10),
(-1, 1, 0)
])
def test_add_param(a, b, expected):
assert add(a, b) == expected
This replaces multiple near‑identical test functions with a single compact one.
5️⃣ Expected Exceptions
import pytest
def div(a, b):
return a / b
def test_div_zero():
with pytest.raises(ZeroDivisionError):
div(1, 0)
6️⃣ Running a subset & coverage
# Run only tests in a specific file
pytest tests/test_api.py
# Run with coverage (requires pytest‑cov)
pip install pytest-cov
pytest --cov=myapp
7️⃣ Good Practices Checklist
- Keep tests in a separate
tests/folder. - Name test files
test_*.pyand test functionstest_*. - Use fixtures for heavy‑weight setup (DB connections, API clients).
- Aim for fast tests – they should run in milliseconds.
- Combine
pytestwithmypyfor type‑checked tests (--check-type).
With pytest you’ll spend less time writing boilerplate and more time verifying that your code works.