Definicja #
Pytest to framework do testowania w Pythonie, który zastąpił wbudowany moduł unittest jako de facto standard w ekosystemie. Wyróżnia się minimalistyczną składnią — testy to zwykłe funkcje Pythona z asercjami assert, bez dziedziczenia po klasach bazowych.
Kluczowe elementy Pytest:
- Prosta składnia — test to funkcja o nazwie zaczynającej się od
test_; asercje przez standardowy Pythonassert; pytest dostarcza szczegółowe komunikaty błędów (introspection) - Fixtures — centralny mechanizm Pytest; funkcje dekorowane
@pytest.fixturedostarczają zasobów testom (baza danych, klient HTTP, dane testowe); wstrzykiwane przez parametry funkcji testowej - Scope fixtures —
function,class,module,session; kontrola kiedy fixture jest tworzone i niszczone - Parametryzacja —
@pytest.mark.parametrizeuruchamia test wielokrotnie z różnymi danymi wejściowymi - Markers —
@pytest.mark.skip,@pytest.mark.xfail,@pytest.mark.slow; kategoryzacja i filtrowanie testów - Conftest.py — plik współdzielonych fixtures i konfiguracji widoczny dla całego drzewa katalogów
- Bogaty ekosystem pluginów — pytest-django, pytest-asyncio, pytest-cov (code coverage), pytest-mock, pytest-xdist (równoległe wykonanie)
Pytest jest standardem testowania dla frameworków Python: Django (pytest-django), FastAPI, Flask. Obsługuje testy asynchroniczne (asyncio) przez pytest-asyncio.
Zastosowania #
- Testy jednostkowe logiki biznesowej w Pythonie — izolowane testowanie funkcji i klas z fixtures jako dependency injection
- Testy integracyjne Django i FastAPI — pytest-django z
@pytest.mark.django_db, TestClient dla HTTP testów - Testy parametryzowane — weryfikacja funkcji z wieloma zestawami danych wejściowych przez
@pytest.mark.parametrize - Data science i ML — testy pipeline'ów przetwarzania danych, walidacja modeli ML i transformacji
- CI/CD — integracja z GitHub Actions, generowanie raportów JUnit XML dla systemów CI
Ścieżka nauki #
Pytest jest obowiązkowym narzędziem dla każdego Python developera dbającego o jakość kodu.
Zacznij od:
- Instalacja:
pip install pytest; uruchamianie:pytestw katalogu projektu - Pierwszy test: plik
test_*.py, funkcjadef test_nazwa():z asercjąassert wynik == oczekiwany - Fixtures:
@pytest.fixturedo przygotowania zasobów; fixturetmp_path,capsys,monkeypatchwbudowane - Parametryzacja:
@pytest.mark.parametrize("input,expected", [(1, 2), (3, 4)])
Następnie pogłębiaj:
- Mockowanie z
pytest-mock(mocker.patch()) — izolacja zależności zewnętrznych - Code Coverage:
pip install pytest-cov; raport:pytest --cov=src --cov-report=html - pytest-django — testowanie aplikacji Django z bazą danych i klientem HTTP
- pytest-asyncio — testy asynchroniczne dla FastAPI i asyncio
FAQ #
- Czym różni się Pytest od unittest?
- unittest to wbudowany moduł Pythona — testy wymagają dziedziczenia po TestCase i użycia metod self.assertEqual(). Pytest jest bardziej zwięzły: testy to funkcje z asercją assert, fixtures zastępują setUp/tearDown, parametryzacja jest prostsza. Pytest jest kompatybilny wstecznie — uruchamia testy unittest. Do nowych projektów rekomendowany jest Pytest.
- Czym są fixtures w Pytest i jak działają?
- Fixture to funkcja dekorowana @pytest.fixture dostarczająca zasoby lub dane testom. Test deklaruje potrzebę fixture przez parametr o tej samej nazwie — Pytest automatycznie wstrzykuje fixture. Fixtures mogą mieć różny zakres (function/module/session), zwracać dane i wykonywać cleanup po teście przez yield.
- Jak uruchomić tylko wybrane testy w Pytest?
- Pytest oferuje wiele sposobów filtrowania: -k 'nazwa' (wyrażenie nazwy testu), -m 'marker' (marker), konkretny plik: pytest tests/test_modul.py, konkretna funkcja: pytest tests/test_modul.py::test_funkcja. Flaga -v pokazuje szczegółowe wyniki, --tb=short skraca traceback.
- Jak mierzyć pokrycie kodu w Pytest?
- Przez plugin pytest-cov: pip install pytest-cov, następnie pytest --cov=src --cov-report=html. Raport HTML generowany w htmlcov/ pokazuje pokryte i niepokryte linie. Wskaźnik pokrycia jest pomocną metryką, ale sama liczba nie gwarantuje jakości testów — liczy się testowanie rzeczywistych ścieżek logiki.