Sobes.tech
Назад к вопросам
Junior — Middle
58

Как реализовать генераторные функции внутри фикстур в pytest для управления их порядком выполнения?

Компании, где спрашивали
Криптонит

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

Генераторные фикстуры в pytest используют, когда нужно выполнить подготовку до теста и очистку после него. Для этого в фикстуре ставят yield: всё до него выполняется перед тестом, всё после — после завершения теста. Такой подход позволяет явно управлять порядком setup/teardown и удобно комбинировать несколько фикстур.

Определение:

Генераторная фикстура — это фикстура, которая содержит yield и разделяет логику на две части: до yield выполняется подготовка тестового окружения, а после yield — завершающие действия, такие как удаление файлов, закрытие соединений или откат состояния. В pytest код после yield запускается только после завершения теста, даже если тест упал, что делает такие фикстуры удобными для управления порядком выполнения и очисткой ресурсов.

Пример использования:

import pytest

@pytest.fixture
def resource():
    print("setup: create resource")
    data = {"status": "ready"}

    yield data

    print("teardown: destroy resource")


def test_example(resource):
    assert resource["status"] == "ready"

Если нужно управлять порядком нескольких фикстур, можно сделать их зависимыми друг от друга:

import pytest

@pytest.fixture
def db():
    print("setup db")
    yield "db"
    print("teardown db")


@pytest.fixture
def user(db):
    print("setup user using", db)
    yield "user"
    print("teardown user")


def test_order(user):
    assert user == "user"

Пояснение кода:

В первом примере всё до yield выполняется перед запуском теста: создаётся ресурс и подготавливаются данные. Значение после yield передаётся в тест как результат фикстуры. После завершения теста pytest продолжает выполнение фикстуры с места после yield и выполняет очистку.

Во втором примере порядок задаётся зависимостями между фикстурами. Сначала pytest вызывает db, затем user, потому что user зависит от db. После теста teardown выполняется в обратном порядке: сначала user, потом db. Это удобно, когда ресурсы создаются вложенно и освобождать их нужно строго в обратной последовательности.

Ключевые моменты:

  • yield в фикстуре делит её на фазу подготовки и фазу очистки.
  • Код до yield выполняется до теста, код после — после теста.
  • Если одна фикстура зависит от другой, pytest выстраивает порядок выполнения по графу зависимостей.
  • Очистка после yield выполняется даже при падении теста.
  • Для сложного порядка лучше явно задавать зависимости между фикстурами, а не рассчитывать на неявное поведение.
  • Генераторные фикстуры особенно полезны для ресурсов, которые нужно гарантированно закрыть или удалить.