JavaRush /Курсы /Модуль 4: FastAPI /Работа с фикстурами Pytest для создания данных

Работа с фикстурами Pytest для создания данных

Модуль 4: FastAPI
5 уровень , 7 лекция
Открыта

Фикстуры (fixtures) в Pytest — это мощный и удобный механизм для подготовки данных или состояния окружения перед выполнением тестов. Проще говоря, фикстуры отвечают на два важных вопроса:

  • Откуда взять данные для тестов?
  • Как настроить "поляну" для тестирования?

Зачем нужны фикстуры?

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

Базовое создание фикстур

Фикстуры в Pytest — это функции, помеченные декоратором @pytest.fixture. Давайте начнем с простого примера.

Пример 1: фиксированные данные

Допустим, у нас есть API для управления пользователями. Мы пишем тест для регистрации нового пользователя. Чтобы не пересоздавать данные вручную, мы определяем фикстуру user_data:


# tests/conftest.py
import pytest

@pytest.fixture
def user_data():
    """Фикстура для создания тестовых данных пользователя"""
    return {"username": "test_user", "password": "secure_password"}

Теперь мы можем использовать эту фикстуру в любом тесте:


# tests/test_users.py
from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_user_registration(user_data):
    """Тестируем регистрацию нового пользователя"""
    response = client.post("/register", json=user_data)
    assert response.status_code == 201
    assert response.json()["username"] == user_data["username"]

Когда вы указываете название фикстуры (user_data) в аргументах функции теста, Pytest автоматически вызывает эту фикстуру и передает результат в тест.

Пример 2: подключение к базе данных

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


# tests/conftest.py
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from myapp.database import Base

DATABASE_URL = "sqlite:///./test.db"

@pytest.fixture(scope="session")
def db_engine():
    """Фикстура для создания движка базы данных"""
    engine = create_engine(DATABASE_URL)
    Base.metadata.create_all(bind=engine)
    yield engine
    Base.metadata.drop_all(bind=engine)

@pytest.fixture
def db_session(db_engine):
    """Фикстура для создания сессии базы данных"""
    SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=db_engine)
    session = SessionLocal()
    yield session
    session.close()

Здесь мы:

  1. Создаем движок базы данных один раз на весь тестовый запуск благодаря scope="session".
  2. Создаем и подготавливаем таблицы перед стартом тестов.
  3. Убираем таблицы после завершения всех тестов (cleanup).
  4. Генерируем отдельные сессии базы данных для каждого теста.

Пример 3: использование нескольких фикстур

Фикстуры можно комбинировать. Например, если нам нужна база данных и заранее созданный пользователь:


# tests/conftest.py
@pytest.fixture
def test_user(db_session):
    """Создание тестового пользователя в базе данных"""
    new_user = User(username="test_user", password="secure_password")
    db_session.add(new_user)
    db_session.commit()
    return new_user

Теперь мы можем использовать test_user в любом тесте:


# tests/test_users.py
def test_get_user(test_user, client):
    response = client.get(f"/users/{test_user.id}")
    assert response.status_code == 200
    assert response.json()["username"] == test_user.username

Пример 4: параметризованные фикстуры

Иногда хочется протестировать один и тот же эндпоинт с разными вариациями данных. Для этого Pytest предлагает параметризованные фикстуры.


# tests/conftest.py
@pytest.fixture(params=[
    {"username": "user1", "password": "pass1"},
    {"username": "user2", "password": "pass2"},
    {"username": "user3", "password": "pass3"}
])
def user_data(request):
    """Фикстура с разными наборами данных"""
    return request.param

Теперь каждый вызов теста будет использовать новый набор данных:


# tests/test_users.py
def test_multiple_users(user_data, client):
    response = client.post("/register", json=user_data)
    assert response.status_code == 201
    assert response.json()["username"] == user_data["username"]

Советы и трюки для работы с фикстурами

  • Используйте файл conftest.py: Поместите часто используемые фикстуры в файл tests/conftest.py, чтобы они автоматически подгружались во всех тестах.
  • Настройте scope: Фикстуры можно выполнять для:
    • function (по умолчанию) — на каждый тест.
    • class — для всех тестов внутри тестового класса.
    • module — для всех тестов внутри файла.
    • session — для всех тестов одного запуска.
  • Используйте yield: Для действий, требующих "уборки" после тестов (например, удаление данных из базы), используйте yield для разделения этапов setup и teardown.
  • Импорты внутри фикстур: Если фикстура использует нечасто используемый модуль, импортируйте его внутри самой функции, чтобы не загружать лишнюю память во время запуска тестов.

Типичные ошибки при работе с фикстурами

Давайте разберем, с какими проблемами вы можете столкнуться:

  1. Забыли указать фикстуру в аргументах теста. Например, вы определили фикстуру, но не использовали её в тесте. Pytest просто её проигнорирует.
  2. Неправильное использование scope. Если вы настроили фикстуру как session, а данные в ней не являются "потокобезопасными", это может вызвать неожиданные баги.
  3. Неправильное завершение работы фикстур. Если забыть удалить временные данные или закрыть соединение, это может привести к "утечкам" в тестовом окружении.

Резюме

Фикстуры Pytest значительно упрощают жизнь разработчикам, избавляя от рутинного создания данных и настройки окружения. На следующей лекции мы разберем запуск тестов и генерацию отчётов о покрытии, чтобы вы смогли оценить, насколько качественно покрыт ваш код. А пока используйте фикстуры и наслаждайтесь магией автоматизации!

1
Задача
Модуль 4: FastAPI, 5 уровень, 7 лекция
Недоступна
Базовая фикстура с фиксированными данными
Базовая фикстура с фиксированными данными
1
Задача
Модуль 4: FastAPI, 5 уровень, 7 лекция
Недоступна
Параметризованная фикстура для тестирования API
Параметризованная фикстура для тестирования API
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ