Программирование PythonТестированиеPython-инженер по автоматизации тестирования

Сессионная фикстура pytest зависит от фикстуры с областью действия «на функцию». Что произойдёт при запуске...

Сессионная фикстура pytest зависит от фикстуры с областью действия «на функцию». Что произойдёт при запуске тестов?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Pytest завершит подготовку такого теста с ошибкой ScopeMismatch. Сессионная фикстура не может напрямую зависеть от фикстуры с более коротким сроком жизни, потому что объект сессии оказался бы связан с уже уничтожаемой зависимостью.

Исторический контекст

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

Чтобы такой механизм оставался предсказуемым, pytest учитывает не только область действия самой фикстуры, но и области действия всей цепочки её зависимостей.

Постановка проблемы

Рассмотрим ситуацию: сессионная фикстура создаёт общий клиент, а для его настройки запрашивает function-scoped фикстуру. Клиент живёт всю тестовую сессию, тогда как его зависимость должна пересоздаваться для каждого теста.

Если разрешить такую зависимость, после первого теста сессионный объект мог бы хранить ссылку на очищенное, изменённое или уже недействительное состояние. Это создало бы скрытую зависимость между тестами и нарушило бы ожидаемый жизненный цикл ресурсов.

Подробное решение

Правило pytest таково: фикстура не может зависеть от другой фикстуры с более узкой областью действия. Области обычно упорядочены от широкой к узкой: session, package, module, class, function.

Например:

import pytest @pytest.fixture def request_context(): return {"token": "test"} @pytest.fixture(scope="session") def api_client(request_context): return Client(request_context)

При запросе api_client pytest обнаружит, что сессионная фикстура пытается получить function-scoped зависимость, и сообщит об ошибке ScopeMismatch. Это проверяется при построении графа зависимостей, до нормального выполнения теста.

Исправление зависит от требуемой изоляции. Если контекст действительно общий и неизменяемый, его можно сделать сессионным. Если контекст должен быть отдельным для каждого теста, клиент тоже следует сделать function-scoped или создавать его внутри более узкой фикстуры.

Нельзя надёжно решить проблему простым сохранением function-scoped объекта в глобальной переменной. Это обходит контроль pytest, но не устраняет очистку, гонки при параллельном запуске и загрязнение состояния.

Ситуация из практики

В интеграционных тестах команда создавала сессионный клиент к тестовой службе. Его зависимостью был function-scoped объект с уникальным идентификатором запроса. Pytest выдавал ScopeMismatch, хотя разработчики рассчитывали переиспользовать сетевое соединение.

Рассматривались два варианта. Сделать идентификатор сессионным было быстро и сохраняло переиспользование клиента, но ухудшало изоляцию тестов. Сделать клиент function-scoped было безопаснее, однако увеличивало число подключений и время прогона.

Выбрали третий вариант: сессионным оставили только безопасный транспортный слой, а клиент, содержащий изменяемый контекст запроса, создавали на уровне функции. В результате соединение переиспользовалось, а данные и заголовки каждого теста оставались изолированными.

Что кандидаты часто упускают

  1. Можно ли сессионной фикстуре зависеть от module-scoped фикстуры?

Нет. module уже уже, чем session, поэтому такая зависимость также вызовет ScopeMismatch. Направление допустимой зависимости должно идти от узкой фикстуры к более широкой, а не наоборот: function-scoped фикстура может использовать session-scoped ресурс.

  1. Что произойдёт, если обе фикстуры явно объявлены с областью действия «на функцию», но одна логически используется как общий ресурс?

Ошибки ScopeMismatch не будет, потому что области совместимы. Однако pytest создаст такую фикстуру отдельно для каждого теста, даже если её результат можно было бы переиспользовать.

Следовательно, корректность и производительность — разные вопросы. Для ускорения область действия можно расширить, но только после проверки, что объект не хранит изменяемое состояние между тестами и корректно очищается.

  1. Может ли function-scoped фикстура использовать session-scoped фикстуру?

Да. Это допустимое направление зависимости: короткоживущий объект получает долгоживущий ресурс. Например, тестовая фикстура функции может использовать общий клиент или соединение, а затем очистить созданные именно ею данные.

Важно разделять жизненные циклы ресурса и состояния. Общий клиент не гарантирует изоляцию автоматически: тестовая фикстура должна сбрасывать контекст, удалять созданные записи или создавать уникальные идентификаторы.