← Назад к вопросам

Что такое pytest fixtures и зачем они нужны?

1.0 Junior🔥 131 комментариев
#Теория тестирования

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое pytest fixtures

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

import pytest

# Объявление фикстуры
@pytest.fixture
def database_connection():
    """Фикстура, создающая и возвращающая соединение с БД."""
    connection = create_db_connection()
    yield connection  # Передаёт управление тесту
    connection.close()  # Выполняет очистку после теста

# Использование фикстуры в тесте
def test_user_count(database_connection):
    # database_connection автоматически передаётся из фикстуры
    count = database_connection.execute("SELECT COUNT(*) FROM users")
    assert count > 0

Основные цели и преимущества использования фикстур

1. Устранение дублирования кода и соблюдение принципа DRY

Вместо того чтобы повторять один и тот же код подготовки (setup) и очистки (teardown) в каждом тесте, логика выносится в фикстуры и переиспользуется.

2. Изоляция тестов и управление зависимостями

Каждый тест получает свой собственный экземпляр данных или ресурса от фикстуры (по умолчанию), что предотвращает нежелательные побочные эффекты между тестами. Зависимости теста становятся явными через список параметров функции.

3. Гибкая область видимости (scope)

Фикстуры могут иметь разную область жизни, что оптимизирует производительность тестов:

@pytest.fixture(scope="session")  # Создаётся один раз за всю сессию
def heavy_resource():
    return initialize_heavy_service()

@pytest.fixture(scope="module")   # Один раз на модуль
def shared_data():
    return load_test_data()

@pytest.fixture(scope="class")    # Один раз на класс
def browser():
    driver = webdriver.Chrome()
    yield driver
    driver.quit()

@pytest.fixture(scope="function") # По умолчанию: для каждой функции
def fresh_user():
    return User(name="Test User")

4. Модульность и композиция

Фикстуры могут зависеть от других фикстур, создавая цепочки иерархии. Это позволяет строить сложные тестовые окружения из простых, переиспользуемых компонентов.

@pytest.fixture
def api_client():
    return APIClient()

@pytest.fixture
def authenticated_client(api_client):  # Зависит от api_client
    api_client.login()
    return api_client

5. Надёжная очистка ресурсов (teardown)

Использование yield в фикстуре позволяет чётко разделить фазу настройки и фазу очистки. Код после yield выполнится гарантированно, даже если тест упадёт с ошибкой. Это критически важно для освобождения ресурсов (закрытие файлов, соединений, остановка браузера).

@pytest.fixture
def temp_file():
    file = open("temp.txt", "w")
    yield file
    file.close()        # Выполнится всегда
    os.remove("temp.txt")

6. Параметризация через фикстуры

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

@pytest.fixture(params=["chrome", "firefox", "edge"])
def browser(request):
    driver = initialize_driver(request.param)
    yield driver
    driver.quit()

def test_login(browser):  # Тест запустится 3 раза для каждого браузера
    browser.get("https://example.com")
    # ... действия с browser

Практический пример комплексного использования

import pytest
import requests

# Фикстура сессии с областью видимости "сессия"
@pytest.fixture(scope="session")
def api_base_url():
    return "https://api.example.com/v1"

# Фикстура зависит от api_base_url
@pytest.fixture(scope="function")
def api_client(api_base_url):
    client = requests.Session()
    client.base_url = api_base_url
    yield client
    client.close()  # Очистка после каждого теста

# Фикстура создаёт тестовые данные
@pytest.fixture
def test_user(api_client):
    user_data = {"name": "Alice", "email": "alice@example.com"}
    response = api_client.post("/users", json=user_data)
    user_id = response.json()["id"]
    yield user_id
    # Удаление пользователя после теста (очистка)
    api_client.delete(f"/users/{user_id}")

# Тест, использующий цепочку фикстур
def test_user_retrieval(api_client, test_user):
    response = api_client.get(f"/users/{test_user}")
    assert response.status_code == 200
    assert response.json()["name"] == "Alice"

Итог: Pytest fixtures — это краеугольный камень эффективной и поддерживаемой автоматизации тестирования на Python. Они превращают хаотичный код подготовки/очистки в структурированную, декларативную и переиспользуемую систему зависимостей, что ведёт к созданию быстрых, изолированных, надёжных и легко читаемых тестов. Понимание и грамотное применение фикстур является одним из ключевых навыков для QA Automation Engineer, работающего с pytest.