Что делает pytest? пока вы пьёте кофе

Вы пишете в консоли pytest tests/. Нажимаете Enter. Идёте за кофе. Через минуту возвращаетесь — зелёный отчёт. Вы думаете, что тесты просто пробежали. Внутри за это время случилась целая эпопея.

Рассказываю по пунктам, от начала до конца.

Этап 1. Сбор тестов (Collection)

Pytest заходит в указанную папку. Проходит по каждому файлу. Смотрит на названия классов и функций. Всё, что начинается с test_ или заканчивается на _test, попадает в список.

На этом этапе срабатывает хук pytest_collection_modifyitems. Он позволяет перетрясти этот список до старта. Убираем медленные тесты для локального запуска. Оставляем только критичные сценарии для быстрой проверки.

Этап 2. Поиск фикстур и подготовка (Setup)

Система смотрит на сигнатуры тестов. Каждая функция с аргументом ищет соответствующую фикстуру. Сначала проверяются скоупы: session, module, class, function.

Самые тяжёлые фикстуры запускаются один раз за всю сессию (например, подключение к базе). Лёгкие — стартуют для каждого теста отдельно.

Если в фикстуре стоит autouse=True, она сработает даже без явного вызова. Отличный способ положить логи или тестовые данные в каждый прогон.

Этап 3. Непосредственный запуск (Execution)

Происходит вызов тестовой функции. Здесь начинается основная магия хуков.

Хук pytest_runtest_makereport перехватывает результат каждого теста в процессе. Он видит, когда тест стартовал, как долго выполнялся и упал ли он. Я часто использую этот хук, чтобы добавлять скриншоты в отчёт, если тест упал.

Этап 4. Очистка и завершение (Teardown)

После выполнения каждого теста запускается механизм разрушения (teardown). Фикстуры сбрасывают состояние. Удаляют временные файлы. Закрывают соединения с базой. Всё это происходит строго в обратном порядке их создания.

Когда все тесты завершены, отрабатывает финальная сессионная очистка.

Кейс из моей практики

Прошлый месяц. Тесты стабильно падали только в CI. Локально — всегда зелёные.

Я добавил хук pytest_runtest_makereport. Написал небольшой скрипт, который сохранял состояние окружения в момент падения. Сравнил логи нескольких запусков. Обнаружил гонку данных между двумя тестами. Они писали в одну таблицу. Поправил изоляцию — флаки ушли.

Многие уверены: разбираться в хуках и жизненном цикле — удел разработчиков, пишущих плагины. На деле это простая бытовая вещь.

Вы добавляете хук, чтобы исключать медленные тесты перед отправкой кода. Добавляете хук, чтобы ловить специфические ошибки в CI. Это такие же инструменты, как assert. Без них вы гадаете на кофейной гуще. С ними вы точно знаете, на каком этапе всё пошло не так.

Что делает pytest? пока вы пьёте кофе | Сетка — социальная сеть от hh.ru