В одном тесте две фикстуры зависят от общей function-scoped фикстуры. Сколько раз pytest создаст общую фикстуру и почему?
pytest создаст общую function-scoped фикстуру один раз для конкретного запуска теста. Обе зависимые фикстуры получат тот же сохранённый результат, потому что pytest кэширует значение фикстуры в пределах области её действия и текущего тестового элемента.
Фикстуры в pytest решают проблему повторяющейся подготовки окружения и симметричной очистки ресурсов. Вместо ручного вызова общего setup-кода тесты объявляют зависимости, а фреймворк сам строит граф подготовки и управляет временем жизни объектов.
Кэширование важно именно для этой модели: зависимость может быть общей для нескольких фикстур, но её создание не должно автоматически дублироваться внутри одного теста.
Предположим, две фикстуры используют одно соединение с базой данных или один временный каталог. Если pytest создаст ресурс дважды, тест может стать медленнее, получить разные объекты вместо одного общего состояния или выполнить лишние побочные действия.
Обратная ошибка тоже опасна: если ресурс ошибочно переиспользуется между независимыми тестами, состояние одного теста может повлиять на другой. Поэтому результат зависит не только от наличия общей зависимости, но и от её scope.
Для каждого тестового элемента pytest ведёт кэш результата фикстуры. Когда первая зависимая фикстура запрашивает resource, pytest выполняет её и сохраняет результат. При последующем запросе resource в рамках того же теста возвращается сохранённое значение, а функция фикстуры повторно не вызывается.
Здесь left и right получают один объект: обе зависимости разрешаются через один кэш фикстуры resource. Порядок подготовки определяется зависимостями, но сам факт наличия двух потребителей не создаёт две копии.
function scope означает, что кэш действует для одного запуска тестового элемента. Для параметризованного теста каждый набор параметров создаёт отдельный тестовый элемент, поэтому фикстура будет выполнена отдельно для каждого набора параметров.
Другие области действия — например, class, module или session — расширяют период жизни кэша. Однако фикстура с более широкой областью не может напрямую зависеть от фикстуры с более узкой областью: это привело бы к использованию уже уничтоженного или неоднозначно привязанного ресурса.
Кэшируется результат фикстуры, а не обязательно копия объекта. Если фикстура возвращает изменяемый объект, все потребители в пределах соответствующей области увидят тот же объект и могут изменить его состояние. Это удобно для намеренно общего ресурса, но опасно при неявном обмене состоянием.
В тестах сервиса две фикстуры — клиент API и проверяющий журнал — зависели от общей фикстуры тестового хранилища. Разработчик сначала создал хранилище отдельно в каждой из двух фикстур. Тесты проходили, но клиент и журнал фактически работали с разными экземплярами, поэтому проверка журнала не отражала действия клиента.
Рассматривались два варианта. Можно было оставить независимое создание ресурсов: это уменьшало связанность, но не позволяло проверять взаимодействие через одно хранилище и увеличивало время подготовки. Можно было передавать ресурс вручную через дополнительные аргументы, но это дублировало управление зависимостями и усложняло сигнатуры тестов.
Выбрали одну общую function-scoped фикстуру, от которой зависели обе потребляющие фикстуры. В результате pytest создавал хранилище один раз на тест, обе фикстуры получали один объект, а между тестами состояние изолировалось.
Изменится ли поведение, если общая фикстура имеет module scope?
Да, объект будет кэшироваться дольше: обычно один экземпляр используется тестами соответствующего модуля, пока не завершится его область действия. Все тесты этого модуля могут наблюдать изменения общего изменяемого объекта, поэтому очистка состояния между тестами становится ответственностью фикстуры или самих тестов.
Создаст ли параметризованная function-scoped фикстура один объект для всех параметров теста?
Нет. Каждый параметр создаёт отдельный запуск тестового элемента, и для каждого такого запуска pytest получает свой результат фикстуры. Поэтому параметризация расширяет набор отдельных экземпляров, даже если область действия фикстуры остаётся function.
Что произойдёт, если две фикстуры изменяют общий изменяемый объект?
Изменения будут видны друг другу, поскольку они работают с одной закэшированной ссылкой. Это может быть намеренным способом подготовить единое состояние, но чаще создаёт скрытую связанность и нестабильность; безопаснее возвращать независимые объекты либо явно очищать общее состояние перед проверкой.