Как параметр scope влияет на выполнение фикстуры в pytest?

«Как параметр scope влияет на выполнение фикстуры в pytest?» — вопрос из категории Фреймворки тестирования, который задают на 24% собеседований AQA / Automation. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Параметр scope фикстуры в pytest определяет её время жизни и частоту создания. Это напрямую влияет на производительность и изоляцию тестов.

Доступные значения scope (от самого короткого до самого долгого):

  • function (по умолчанию): Фикстура создается заново для каждого тестового случая. Обеспечивает максимальную изоляцию.
  • class: Фикстура создается один раз для каждого тестового класса.
  • module: Фикстура создается один раз для каждого модуля (файла) с тестами.
  • package: Фикстура создается один раз для каждого пакета (директории).
  • session: Фикстура создается единожды за всю сессию выполнения тестов (за один запуск pytest).

Практический пример выбора scope для тестирования БД:

import pytest
import sqlite3

# Медленная операция — создаем соединение один раз на модуль
@pytest.fixture(scope="module")
def db_connection():
    print("n[SETUP] Creating database connection")
    conn = sqlite3.connect(":memory:")
    # Инициализируем схему БД
    conn.execute("CREATE TABLE users (id INT, name TEXT)")
    yield conn  # Отдаем соединение тестам
    print("n[TEARDOWN] Closing database connection")
    conn.close()

# Быстрая операция — создаем транзакцию для каждого теста
@pytest.fixture(scope="function")
def db_transaction(db_connection):
    print("  [SETUP] Beginning transaction")
    db_connection.execute("BEGIN")
    yield
    print("  [TEARDOWN] Rolling back transaction")
    db_connection.rollback()  # Откатываем изменения после каждого теста

def test_user_insert(db_connection, db_transaction):
    db_connection.execute("INSERT INTO users VALUES (1, 'Alice')")
    # Тест 1

def test_user_count(db_connection, db_transaction):
    # Тест 2: БД чистая, т.к. транзакция откатилась
    count = db_connection.execute("SELECT COUNT(*) FROM users").fetchone()[0]
    assert count == 0

Вывод: scope="module" для db_connection ускоряет тесты, избегая пересоздания соединения. scope="function" для db_transaction гарантирует изоляцию данных между тестами.