Ответ
Фикстура (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, сразу понятно, с чем работаешь. Никакого шума. - Надёжность зашкаливает. Очистка после теста — это не пожелание, а железное правило. Один тест не нагадит в данных для другого. Доверия ебать ноль было к ручному клинапу, а тут — всё автоматом.
- Гибкость — овердохуища. Через параметризацию можно одну фикстуру гонять с разными данными. Мощнейшая штука.
Короче, чувак, если ещё не юзаешь — начинай. Сначала мозг немного взрывается, но когда врубаешься, назад дороги нет. Тесты становятся аккуратными и управляемыми. Красота!