JavaRush /Курси /Модуль 4: FastAPI /Робота з fixtures Pytest для створення даних

Робота з fixtures 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: параметризовані фікстури

Інколи хочеться протестувати той самий endpoint з різними варіаціями даних. Для цього 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 значно спрощують життя розробникам, позбавляючи від рутинного створення даних і налаштування оточення. На наступній лекції ми розберемо запуск тестів і генерацію звітів про покриття, щоб ти зміг оцінити, наскільки якісно покритий твій код. А поки використовуй фікстури і насолоджуйся магією автоматизації!

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ