Для чего используются фикстуры в pytest и как их применять?

Ответ

Фикстуры в pytest — это функции, которые предоставляют предсказуемую, фиксированную среду для тестов. Они используются для подготовки данных, настройки соединений (например, с БД) или создания объектов, необходимых для тестирования.

Принцип работы: Код фикстуры выполняется до запуска теста, который её запрашивает. Если используется yield, то фикстура разделяется на две части:

  1. Setup: Код до yield (подготовка данных).
  2. Teardown: Код после yield (очистка ресурсов), который выполняется после завершения теста.

Пример:

import pytest
import tempfile
import os

# Фикстура создает временный файл и передает его имя в тест
@pytest.fixture
def temp_file():
    # Setup: создаем файл
    fp = tempfile.NamedTemporaryFile(delete=False, mode='w+')
    fp.write('test data')
    fp.close()

    yield fp.name  # Передаем управление и данные тесту

    # Teardown: удаляем файл после теста
    os.unlink(fp.name)

# Тест принимает имя фикстуры в качестве аргумента
def test_read_from_temp_file(temp_file):
    with open(temp_file, 'r') as f:
        content = f.read()
    assert content == 'test data'

Ключевые преимущества:

  • Переиспользование кода: Одна фикстура может использоваться во многих тестах.
  • Изоляция тестов: Каждый тест получает свой собственный экземпляр фикстуры (по умолчанию).
  • Управление ресурсами: Гарантированная очистка ресурсов благодаря yield.
  • Гибкость: Область видимости фикстуры (scope) можно настроить на уровне функции, класса, модуля или всей сессии.

Ответ 18+ 🔞

Слушай, а вот эти ваши фикстуры в pytest — это же просто песня, блядь! Представь себе: ты пишешь тесты, а тебе каждый раз надо одно и то же говно подготавливать — базу накатить, файлик создать, объект сконфигурировать. Так вот, чтобы не повторяться, как попугай ёбаный, и придумали фикстуры.

Это, по сути, такие функции-обслуги. Они всё за тебя делают до того, как твой тест начнётся. А если использовать yield, так они ещё и приберутся после, как заботливая тётя Зина, которая за тобой тарелки моет. Охуенно же!

Смотри, как это выглядит на практике. Вот тебе классический пример с временным файлом:

import pytest
import tempfile
import os

# Вот она, мать её, фикстура!
@pytest.fixture
def temp_file():
    # Эта часть — setup, подготовка. Создаём файл.
    fp = tempfile.NamedTemporaryFile(delete=False, mode='w+')
    fp.write('test data')
    fp.close()

    yield fp.name  # А вот тут мы передаём управление тесту и кидаем ему имя файла.

    # А эта часть — teardown, разбор полётов. Файл удаляем. Выполнится ПОСЛЕ теста.
    os.unlink(fp.name)

# А вот тест, который эту фикстуру жрёт.
def test_read_from_temp_file(temp_file):
    with open(temp_file, 'r') as f:
        content = f.read()
    assert content == 'test data'

Видишь магию? Тесту похуй, откуда файл взялся. Он просто его получил, проверил и успокоился. А вся грязная работа — создание и удаление — осталась за скобками, в фикстуре. Красота, ёпта!

И главные плюсы, которые просто выносят мозг:

  • Не повторяйся, мудила! Написал фикстуру один раз — юзай в сотне тестов.
  • Изоляция — наше всё. По умолчанию каждый тест получает свою свеженькую копию данных, чтобы они друг другу не мешали, как пьяные соседи на кухне.
  • Ресурсы под контролем. С yield ты точно знаешь, что всё, что открыл, — закроется. Никаких утечек.
  • Гибкость пиздец. Можно сделать так, чтобы фикстура жила на протяжении одного теста, всего класса, модуля или даже всей тестовой сессии. Это через параметр scope настраивается.

В общем, вещь архиполезная. Сначала кажется, что лишняя сущность, а потом без неё жить не можешь, как без кофе по утрам.