Что такое фикстуры (fixtures) в pytest и как их применяют?

Ответ

Фикстуры (fixtures) в pytest — это функции с декоратором @pytest.fixture, предназначенные для подготовки и очистки тестового окружения. Они реализуют паттерн dependency injection, автоматически предоставляя ресурсы тестовым функциям, которые объявляют их в качестве параметров.

Основные преимущества:

  • Устранение дублирования кода для setup/teardown.
  • Изоляция тестов через управление состоянием.
  • Гибкость областей видимости: function (по умолчанию), class, module, session.
  • Надёжный teardown через yield или addfinalizer.

Пример фикстуры с setup и teardown:

import pytest

@pytest.fixture
def database_connection():
    # Setup: создание соединения
    conn = create_db_connection("test_db")
    yield conn  # Значение передаётся тесту
    # Teardown: закрытие соединения (выполняется после теста)
    conn.close()

# Тест использует фикстуру как параметр
def test_insert_user(database_connection):
    result = database_connection.execute("INSERT INTO users ...")
    assert result.rowcount == 1

Практическое применение:

  1. Подготовка данных: создание тестовых объектов, заполнение БД.
  2. Конфигурация: инициализация клиентов API, настройка временных каталогов.
  3. Мокирование: возвращение заглушек для внешних сервисов.

Фикстуры — это краеугольный камень для построения масштабируемых и поддерживаемых тестовых наборов в pytest.

Ответ 18+ 🔞

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

Представь: ты пишешь тест, а тебе надо базу данных поднять, таблицы накатить, тестовые данные засунуть. Без фикстур это выглядит как пиздец: в каждом тесте один и тот же код копипастишь, а если что-то поменялось — иди и во всех ста местах правь, волнение ебать, терпения ноль ебать.

А с фикстурами — красота. Объявляешь один раз эту магическую функцию, навешиваешь @pytest.fixture, и всё, пизда. Теперь любой тест может её просто попросить по имени в параметрах, и pytest сам, как хитрая жопа, всё подставит.

import pytest

@pytest.fixture
def database_connection():
    # Вот тут ты делаешь всю грязную работу — setup
    conn = create_db_connection("test_db")
    yield conn  # А это — момент истины, когда ты отдаёшь ресурс тесту
    # А вот это выполнится ПОСЛЕ теста, хоть он там обосрись или нет — teardown
    conn.close()

def test_insert_user(database_connection):
    result = database_connection.execute("INSERT INTO users ...")
    assert result.rowcount == 1

Смотри, как элегантно: database_connection — это как будто твой личный дворецкий. Ты в тесте просто говоришь: «Эй, дай-ка сюда соединение с базой». А он тебе уже готовое, тёпленькое, подносит. А после того как ты всё проверил и наговнокодил, он тихонечко зайдёт и всё закроет, чтобы ресурсы не висели. Красота, ёпта!

А самое охуенное — это области видимости (scope). По умолчанию фикстура создаётся заново для каждого теста (function). Но если тебе, например, тяжёлое соединение настраивать — овердохуища времени уходит — можно сделать scope='session'. Тогда эта хуйня создастся один раз на весь прогон тестов и будет переиспользоваться, как последняя сигарета в пачке. Есть ещё class и module — тоже полезные штуки.

Где это реально вставляет мозги в пазлы:

  1. Подготовка данных. Не надо в каждом тесте создавать юзера User(name='Вася', email='vasya@pidor.ru'). Объявил фикстуру @pytest.fixture def vasya(): return User(...) и таскай этого Васю по всем тестам.
  2. Конфигурация всякой хуйни. Клиент для АПИ, временная папка для файлов, настройки драйвера браузера — всё это идеальные кандидаты.
  3. Моки и заглушки. Нужно отрезать тест от внешнего мира? Фикстура может вернуть тебе красивый мок, который делает вид, что он платёжный гейт, а на самом деле просто сосалка.

Короче, если ты пишешь тесты на pytest и не используешь фикстуры — ты, прости, мудак. Это тот самый краеугольный камень, на котором держится вся разумная и поддерживаемая тестовая архитектура. Всё остальное — просто детали.