Общие практики pytest
Применяй единые технические приёмы pytest, не определяя, что именно должен проверять конкретный компонент. Состав сценариев, ожидаемые результаты и технологические гарантии бери из требований тестируемого компонента.
Порядок работы
- Изучи инструкции репозитория и существующую организацию тестов.
- Получи перечень проверяемых сценариев из требований компонента.
- Раздели unit- и integration-тесты.
- Размести фикстуры и фабрики на минимально необходимом общем уровне.
- Параметризуй одинаковые по структуре сценарии.
- Настрой асинхронное выполнение и инфраструктурный lifecycle при необходимости.
- Запусти узкие проверки, затем обязательный полный набор и покрытие.
Не добавляй happy path, граничные случаи, ошибочные исходы, инварианты или приоритеты покрытия самостоятельно.
Структура
Используй базовое разделение:
src/tests/
├── units/
└── integration/
- Внутри повторяй только полезную часть структуры исходного кода.
- Не создавай пустые каталоги заранее.
- Unit-тест проверяет локальный контракт с контролируемыми зависимостями.
- Integration-тест проверяет взаимодействие написанного в проекте кода с настоящей технологической инфраструктурой.
- Не смешивай unit- и integration-цель в одном тесте.
Фикстуры и фабрики
- Используй локальную фикстуру, если она нужна одному модулю.
- При использовании несколькими модулями переноси её в ближайший общий
conftest.py. - Не дублируй фикстуры и фабрики.
- Фабрику предоставляй фикстурой.
- Значения по умолчанию фабрики должны создавать валидный объект.
- Не скрывай случайность, I/O и лишнее поведение внутри фабрики.
- Расширяй scope только при измеримой необходимости.
- Используй
autouseтолько для необходимой поперечной изоляции между тестами. - Удаляй пустой
conftest.py. - Какие объекты создавать фабриками, определяют требования компонента.
Decision tree и параметризация приведены в fixtures-and-parametrization.md.
Тестовые двойники
- В unit-тесте используй небольшую fake- или stub-реализацию внешней зависимости.
- Реализуй только необходимый публичный контракт.
- Предпочитай понятный fake хрупким цепочкам
MockиAsyncMock. - В integration-тесте не заменяй проверяемую технологическую инфраструктуру mock-объектом.
- Не проверяй внутреннее поведение сторонних библиотек.
Параметризация
- Объединяй сценарии с одинаковой последовательностью Arrange–Act–Assert через
pytest.mark.parametrize. - Всегда задавай
ids, описывающие смысл вариантов. - Не объединяй существенно разные сценарии ради сокращения кода.
- Для сложного набора входов и ожиданий используй неизменяемый case-объект.
Маркеры
- Помечай integration-тесты
@pytest.mark.integration. - Регистрируй каждый пользовательский маркер в конфигурации pytest.
- Добавляй остальные маркеры только при реальном использовании.
- Маркеры дополняют структуру каталогов, но не заменяют её.
Асинхронные тесты
- Используй
pytest-asyncioи явно выбранный проектом asyncio mode. - Не управляй event loop вручную внутри теста.
- Отменяй созданные фоновые задачи и дожидайся их завершения.
- Не оставляй pending tasks после теста.
- Подменяй время, ожидания и сигналы управляемыми часами и событиями.
- Не используй реальные долгие
sleep. - Ограничивай ожидание асинхронного результата timeout.
Подробности — в async-and-stability.md.
Интеграционная инфраструктура
Поддерживай два согласованных проектом режима:
- локальный — тестовая сессия сама поднимает и освобождает инфраструктуру;
- внешний — тесты подключаются к уже подготовленным зависимостям и не управляют их lifecycle.
Не навязывай имя переключателя и переменных подключения, если в проекте уже есть конвенция.
Общие требования локального режима:
- запускать инфраструктуру автоматически через subprocess;
- создавать конфигурацию вне репозитория в уникальном временном каталоге;
- использовать уникальные имена файлов, проекта и глобальных ресурсов;
- выбирать порты динамически;
- проверять готовность активной проверкой с timeout;
- выполнять cleanup в
finally, включая частично успешный startup; - поддерживать параллельные прогоны без общего namespace.
Общие требования внешнего режима:
- получать подключения из переменных окружения;
- не создавать, не изменять и не останавливать внешнюю инфраструктуру;
- явно обрабатывать отсутствие обязательных параметров;
- проверять готовность;
- сохранять изоляцию ресурсов параллельных прогонов.
Одна session-scoped фикстура владеет общим lifecycle и возвращает минимальный типизированный runtime-контекст. Технологические фикстуры выполняют подготовку схемы, создание клиентов и очистку состояния штатными средствами технологии. Не закрепляй эти механизмы в общем скиле.
Подробности — в integration-infrastructure.md.
Наблюдаемое поведение и стабильность
- Проверяй публично наблюдаемый результат и согласованные побочные эффекты.
- Не проверяй приватные методы и внутреннюю последовательность вызовов без контрактной причины.
- Не завязывай тест на порядок запуска.
- Контролируй случайные значения, время и timezone.
- Жди наблюдаемое условие вместо произвольного
sleep. - Не маскируй flaky-тест безусловным retry.
- После теста не оставляй процессы, задачи, соединения и временные файлы.
Запуск и покрытие
Используй команды, принятые репозиторием. Для проекта на uv:
uv run pytest
uv run pytest src/tests/units
uv run pytest -m integration
uv run pytest path/to/test_file.py
uv run pytest path/to/test_file.py::test_name
uv run pytest --cov=src --cov-report=term-missing
- Настраивай source и форматы отчётов согласно требованиям проекта.
- При раздельных прогонах объединяй coverage-данные штатным способом инструмента.
- Не устанавливай проценты, приоритеты и исключения покрытия в общем скиле.
- Не создавай искусственные тесты только ради процента.
Границы
В область скила входят:
- конфигурация pytest, pytest-asyncio и pytest-cov;
- структура unit/integration;
- фикстуры, фабрики и
conftest.py; - test doubles;
- параметризация и маркеры;
- общие правила асинхронности и стабильности;
- общий lifecycle временной интеграционной инфраструктуры;
- команды запуска и сбор покрытия.
Не входят:
- выбор тестовых сценариев и ожидаемых результатов;
- проверки конкретных инвариантов, операций, endpoint-ов и протоколов;
- SQL, миграции и очистка конкретной БД;
- stream, subject, ACK и другие правила брокера;
- требования к проценту покрытия;
- тестирование поведения сторонних библиотек.
Критерии готовности
- Состав сценариев получен из требований компонента.
- Unit- и integration-тесты разделены.
- Фикстуры и фабрики не дублируются.
- Параметризация содержит читаемые
ids. - Пользовательские маркеры зарегистрированы.
- Асинхронные задачи корректно завершаются.
- Инфраструктура изолирована, проверяет готовность и освобождается автоматически.
- Локальный и внешний режимы соблюдают согласованный контракт проекта.
- Команды запуска и сбор покрытия работают.
- Полный обязательный набор тестов проходит.
Материалы
- Фикстуры и параметризация
- Асинхронность и стабильность
- Интеграционная инфраструктура