Что такое фикстура (fixture) в pytest?

Ответ

Фикстура (fixture) в pytest — это мощный механизм для настройки предварительных условий и очистки после выполнения тестов. По сути, это функция, которая подготавливает данные, состояние системы или ресурсы (например, подключение к БД, браузер для UI-тестов), которые затем используются в тестовых функциях.

Ключевые особенности:

  • Объявляется с помощью декоратора @pytest.fixture.
  • Передаётся в тест как параметр по имени фикстуры.
  • Поддерживает различные области видимости (scope):
    • function (по умолчанию) — выполняется для каждого теста.
    • class — один раз для класса тестов.
    • module — один раз для модуля.
    • session — один раз за всю сессию запуска тестов.
  • Фикстуры могут зависеть от других фикстур.
  • Поддерживают финализацию (очистку) через yield или request.addfinalizer.

Пример фикстуры для теста API:

import pytest
import requests

@pytest.fixture(scope="module")
def api_client():
    """Фикстура создаёт и возвращает клиент для работы с API."""
    base_url = "https://api.example.com"
    session = requests.Session()
    session.headers.update({"Content-Type": "application/json"})

    # Здесь может быть логин и получение токена
    # login_response = session.post(f"{base_url}/login", json=credentials)
    # session.headers.update({"Authorization": f"Bearer {token}"})

    yield session  # Возвращаем объект сессии тестам

    # Финализация (закрытие сессии) выполнится после всех тестов в модуле
    session.close()

@pytest.fixture
def create_test_user(api_client):
    """Фикстура, зависящая от api_client, создаёт тестового пользователя и возвращает его данные."""
    user_data = {"name": "Test User", "email": "test@example.com"}
    response = api_client.post("/users", json=user_data)
    assert response.status_code == 201
    created_user = response.json()

    yield created_user  # Тест получает данные пользователя

    # После теста удаляем созданного пользователя (очистка)
    api_client.delete(f"/users/{created_user['id']}")

def test_user_creation(create_test_user):
    """Тест использует фикстуру create_test_user."""
    user = create_test_user
    assert user["id"] is not None
    assert user["name"] == "Test User"

Преимущества для QA:

  • Устранение дублирования: Общая логика настройки выносится в одно место.
  • Читаемость: Тесты становятся чище и сфокусированы на проверках.
  • Надёжность: Гарантированная очистка тестовых данных после прогона, что предотвращает влияние тестов друг на друга.
  • Гибкость: Легко менять конфигурацию тестового окружения через параметризацию фикстур.

Ответ 18+ 🔞

А, фикстуры в pytest! Ну это, блядь, просто песня, а не инструмент. Сидишь такой, пишешь тесты, и каждый раз одно и то же: подключись к базе, создай юзера, потом удали, открой браузер, закрой... Терпения ебать ноль становится. А тут — раз, и волшебство.

Представь себе, чувак, это как такая хитрая жопа, которая всё за тебя делает. Настроит, подготовит, подсунет тебе в тест готовенькое, а потом ещё и приберётся. Красота, ёпта.

Вот в чём соль, если по-простому:

  • Это обычная функция, но с магическим декоратором @pytest.fixture. Надел шляпу — и ты уже фикстура.

  • Называешь её как хочешь, а в тест она попадает просто именем параметра. Pytest сам всё найдёт и подставит. Удивление пиздец, когда впервые видишь.

  • Самое важное — scope (область видимости). Это чтобы не делать одно и то же сто раз, если не надо.

    • function (по умолчанию) — запустится для каждого теста отдельно. Надёжно, но может быть долго.
    • class — один раз на весь класс тестов. Уже лучше.
    • module — один раз на файл. Экономия, мать его.
    • session — один раз за весь прогон. Вот это мощь, когда дорогая операция типа запуска браузера или создания тестовой БД.
  • Фикстуры могут цепляться друг за друга, как пьяные матросы. Одна зависит от другой, та от третьей... Главное, чтоб зацикливания не было, а то нихуя не запустится.

  • Финализация — это святое! Чистим за собой бардак. Раньше через addfinalizer мучались, а сейчас проще — через yield. Всё что до yield — настройка, всё что после — уборка. Гениально и просто.

Смотри, как это в жизни для API-тестов выглядит:

import pytest
import requests

@pytest.fixture(scope="module")
def api_client():
    """Фикстура создаёт и возвращает клиент для работы с API."""
    base_url = "https://api.example.com"
    session = requests.Session()
    session.headers.update({"Content-Type": "application/json"})

    # Тут могла бы быть авторизация, но её нет, потому что лень
    # Представь, что токен тут есть, ядрёна вошь

    yield session  # Вот тут отдаём сессию тестам. Тесты работают.

    # А это выполнится ПОСЛЕ всех тестов в модуле. Закрываем лавочку.
    session.close()

@pytest.fixture
def create_test_user(api_client):
    """А эта фикстура уже зависит от клиента. Создаёт юзера, отдаёт его тесту, а потом стирает с лица земли."""
    user_data = {"name": "Test User", "email": "test@example.com"}
    response = api_client.post("/users", json=user_data)
    assert response.status_code == 201  # Ёперный театр, а если не 201?
    created_user = response.json()

    yield created_user  # Лови, тест, свеженького юзера!

    # Тест отстрелялся — юзер больше не нужен. В пизду.
    api_client.delete(f"/users/{created_user['id']}")

def test_user_creation(create_test_user):
    """А вот сам тест. Чистенький, красивенький. Никакого шаманства."""
    user = create_test_user
    assert user["id"] is not None
    assert user["name"] == "Test User"

И почему это кайф для QA-инженера:

  • Нет дубляжа кода. Всё общее — в одном месте. Захотел поменять логин — поправил одну фикстуру, а не двадцать тестов.
  • Тесты читаются как книга. Вошел, увидел create_test_user, сразу понятно, с чем работаешь. Никакого шума.
  • Надёжность зашкаливает. Очистка после теста — это не пожелание, а железное правило. Один тест не нагадит в данных для другого. Доверия ебать ноль было к ручному клинапу, а тут — всё автоматом.
  • Гибкость — овердохуища. Через параметризацию можно одну фикстуру гонять с разными данными. Мощнейшая штука.

Короче, чувак, если ещё не юзаешь — начинай. Сначала мозг немного взрывается, но когда врубаешься, назад дороги нет. Тесты становятся аккуратными и управляемыми. Красота!