Introduction to pytest (Part 1): Basic tests and markers
If unittest is the standard library stalwart, pytest is the community’s daily driver: plain functions, expressive assert introspection, and plugin hooks that integrate with IDEs and CI.
pip install pytest
📚 Prerequisites
- unittest Part 2 is helpful but not mandatory.
🎯 What you'll learn
- Author tests as
test_*functions with simpleassert. - Run subsets of a suite by path, node id, or keyword.
- Attach markers (metadata “attributes”) for filtering slow or network tests.
First pytest module
# test_add.py
from math_utils import add
def test_add_basic():
assert add(2, 3) == 5
def test_add_identity():
assert add(0, 7) == 7
pytest -q
Failures print intermediate sub-expressions automatically—no need for self.assertEqual boilerplate.
Markers as test attributes
import pytest
@pytest.mark.slow
def test_heavy_import():
import expensive_optional_dep # noqa: F401
Run everything except slow tests:
pytest -m "not slow"
Register custom markers in pytest.ini to avoid typos:
[pytest]
markers =
slow: long-running integration scenario
Targeted runs
pytest tests/test_api.py
pytest tests/test_api.py::test_health
pytest -k "health and not slow"
💡 Key takeaways
- Pytest’s ergonomics encourage writing more tests—lower friction means higher coverage naturally.
➡️ Next steps
Layer fixtures, parametrization, and ASGI clients in pytest Part 2.