Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Fixtures: создаём данные один раз
simple_fixtures

Fixtures: создаём данные один раз

@pytest.fixture, scope фикстур, yield для cleanup, conftest.py

Вы уже умеете группировать тесты маркерами и запускать с разными данными. Но что если один и тот же setup повторяется в 10 тестах?

Цель: научиться использовать фикстуры для переиспользования setup-кода и избавиться от дублирования.

Проблема: дублирование setup-кода

# ❌ ПЛОХО — повторяем создание account в каждом тесте def test_deposit(): account = BankAccount(100) # Дублирование account.deposit(50) assert account.balance == 150 def test_withdraw(): account = BankAccount(100) # Дублирование account.withdraw(30) assert account.balance == 70 def test_multiple_deposits(): account = BankAccount(100) # Дублирование account.deposit(50) account.deposit(20) assert account.balance == 170

Проблемы:

  • ❌ Копипаста: BankAccount(100) повторяется 3 раза
  • ❌ Если нужно изменить initial_balance — менять во всех тестах
  • ❌ Сложно поддерживать при росте тестов

Решение: @pytest.fixture

Базовая фикстура

import pytest from src.bank_account import BankAccount @pytest.fixture def account(): """Создаёт BankAccount с балансом 100""" return BankAccount(100) # ✅ ХОРОШО — используем фикстуру def test_deposit(account): """Тест пополнения""" account.deposit(50) assert account.balance == 150 def test_withdraw(account): """Тест снятия""" account.withdraw(30) assert account.balance == 70

Что делает pytest:

  1. Видит параметр account в тесте
  2. Находит фикстуру с именем account
  3. Вызывает фикстуру ПЕРЕД тестом
  4. Передаёт результат в тест как аргумент

✅ Теперь setup в одном месте!

Как это работает

@pytest.fixture def account(): print("🔧 Setup: создаём account") return BankAccount(100) def test_deposit(account): print("🧪 Тест запущен") account.deposit(50) assert account.balance == 150

Вывод:

🔧 Setup: создаём account
🧪 Тест запущен
PASSED

Фикстура вызывается ПЕРЕД каждым тестом!

Множественные фикстуры

Несколько фикстур в одном тесте

@pytest.fixture def empty_account(): """Пустой счёт""" return BankAccount(0) @pytest.fixture def rich_account(): """Счёт с большим балансом""" return BankAccount(10000) def test_transfer(empty_account, rich_account): """Перевод денег между счетами""" amount = 500 rich_account.withdraw(amount) empty_account.deposit(amount) assert rich_account.balance == 9500 assert empty_account.balance == 500

Фикстура использует другую фикстуру

@pytest.fixture def user(): """Создаёт пользователя""" return User("Alice", 25) @pytest.fixture def user_with_account(user): """Создаёт пользователя СО счётом""" account = BankAccount(1000) user.account = account return user def test_user_can_deposit(user_with_account): """Пользователь может пополнить счёт""" user_with_account.account.deposit(500) assert user_with_account.account.balance == 1500

Scope фикстур: когда создавать объекты

По умолчанию: scope="function"

@pytest.fixture # scope="function" по умолчанию def account(): print("🔧 Создаём account") return BankAccount(100) def test_deposit(account): pass def test_withdraw(account): pass

Результат: каждый тест получает НОВЫЙ объект.

scope="module" — один объект для всех тестов

@pytest.fixture(scope="module") def database_connection(): """Подключение к БД (медленно!)""" connection = connect_to_db() return connection def test_insert_user(database_connection): pass def test_select_user(database_connection): pass

✅ Подключение создано ОДИН раз для всего модуля!

Scope опции

@pytest.fixture(scope="function") # Каждый тест (default) @pytest.fixture(scope="class") # Один раз для класса @pytest.fixture(scope="module") # Один раз для файла @pytest.fixture(scope="session") # Один раз для всей сессии

Когда использовать:

  • function — быстрые объекты (User, BankAccount) ✅ Default
  • module — медленные объекты (DB connection, API client)
  • session — очень медленные (Docker container, test database)

Fixtures с cleanup: yield (bonus)

Проблема: нужно закрыть ресурсы

@pytest.fixture def temp_file(): """Создаёт временный файл""" file = open("test.txt", "w") file.write("test data") file.close() return "test.txt" # ❌ Файл останется после теста!

Решение: yield для cleanup

@pytest.fixture def temp_file(): """Создаёт временный файл и удаляет после теста""" # Setup filename = "test.txt" with open(filename, "w") as f: f.write("test data") yield filename # Возвращаем в тест # Teardown (выполнится ПОСЛЕ теста) import os os.remove(filename) def test_read_file(temp_file): """Тест чтения файла""" with open(temp_file, "r") as f: content = f.read() assert content == "test data" # После этого теста файл удалится!

Порядок выполнения:

  1. Setup: создаём файл
  2. yield filename → передаём в тест
  3. Тест выполняется
  4. Teardown: удаляем файл

Практический пример: полный набор фикстур

# tests/conftest.py (фикстуры доступны во ВСЕХ тестах) import pytest from src.bank_account import BankAccount from src.user import User @pytest.fixture def empty_account(): """Пустой банковский счёт""" return BankAccount(0) @pytest.fixture def account(): """Счёт с начальным балансом""" return BankAccount(100) @pytest.fixture def user(): """Пользователь""" return User("Alice", 25) @pytest.fixture def user_with_account(user, account): """Пользователь со счётом""" user.account = account return user @pytest.fixture(scope="module") def database(): """Подключение к БД (медленно)""" db = connect_to_test_db() yield db db.close()

Где хранить фикстуры

Вариант 1: в том же файле с тестами

# tests/test_bank_account.py @pytest.fixture def account(): return BankAccount(100) def test_deposit(account): pass

Когда: фикстура используется ТОЛЬКО в этом файле.

Вариант 2: в conftest.py (глобально)

# tests/conftest.py @pytest.fixture def account(): return BankAccount(100)

Когда: фикстура используется в НЕСКОЛЬКИХ файлах.

✅ Pytest автоматически находит conftest.py и загружает фикстуры!

Что вы изучили

  • @pytest.fixture — переиспользование setup-кода
  • Scope фикстур — function, module, session
  • yield — cleanup после тестов
  • conftest.py — глобальные фикстуры
  • Композиция фикстур — фикстура использует другую фикстуру
  • Избавились от дублирования — DRY в тестах

Устранение неисправностей

Проверьте свои знания

Вопросы ещё не добавлены

Вопросы для этой подтемы ещё не добавлены.

Далее: Отладка: понимаем ошибки