Ответ
Фикстуры в pytest — это функции, которые предоставляют тестовые данные, состояние или ресурсы, автоматически выполняя настройку (setup) и очистку (teardown). Они объявляются декоратором @pytest.fixture.
Базовый пример:
import pytest
@pytest.fixture
def database_connection():
# Setup: создание соединения
conn = create_connection("localhost", "test_db")
yield conn # Передача ресурса тесту
# Teardown: закрытие соединения (выполняется после теста)
conn.close()
def test_user_insert(database_connection):
result = database_connection.execute("INSERT INTO users VALUES ('alice')")
assert result.rowcount == 1
Области видимости (scope):
@pytest.fixture(scope="function") # По умолчанию — для каждой функции
@pytest.fixture(scope="class") # Один раз для класса тестов
@pytest.fixture(scope="module") # Один раз для модуля
@pytest.fixture(scope="session") # Один раз за сессию тестирования
Зависимости между фикстурами:
@pytest.fixture
def config():
return {"host": "localhost", "port": 5432}
@pytest.fixture
def db_connection(config): # Фикстура использует другую фикстуру
return Database(host=config["host"], port=config["port"])
Параметризованные фикстуры:
@pytest.fixture(params=["sqlite", "postgres", "mysql"])
def database(request):
if request.param == "sqlite":
return SQLiteDatabase(":memory:")
elif request.param == "postgres":
return PostgresDatabase("localhost")
# Тест запустится трижды с разными базами данных
def test_query(database):
assert database.query("SELECT 1") == 1
Практические применения:
- Тестовые данные — подготовка объектов моделей
- Внешние зависимости — моки API, временные файлы
- Контекст выполнения — настройка окружения (dev/staging)
- Очистка ресурсов — удаление временных данных после тестов
Автоматическое использование через conftest.py:
# conftest.py (фикстуры доступны во всех тестах директории)
import pytest
@pytest.fixture(autouse=True) # Автоматически для каждого теста
def log_test_start():
print("n--- Test started ---")
yield
print("--- Test finished ---") Ответ 18+ 🔞
А, фикстуры в pytest! Ну это ж, блядь, святая святых, основа основ, как табуретка под жопой, когда пьешь чай на кухне. Без неё вроде и можно, но неудобно, сука, и всё время падаешь.
Смотри, фикстура — это такая функция-обслуга, которая тебе всё приготовит, подаст, а потом, когда ты нажрался, ещё и посуду за тобой помоет. Объявляется через @pytest.fixture. Вот смотри, элементарщина:
import pytest
@pytest.fixture
def database_connection():
# Это setup — накрываешь на стол
conn = create_connection("localhost", "test_db")
yield conn # А это — "на, жри, чмошник!"
# А это teardown — убираешь за ним говно
conn.close()
def test_user_insert(database_connection):
result = database_connection.execute("INSERT INTO users VALUES ('alice')")
assert result.rowcount == 1
Видишь магию? yield — это гениально. Всё до него — подготовка, всё после — уборка трупов. Красота, ёпта!
А ещё у них, у этих фикстур, есть, блядь, области видимости, как у кота, который метит углы. Можно настроить, чтобы она один раз на всю тусовку работала, а не для каждого теста по новой городить:
@pytest.fixture(scope="function") # По умолчанию — новый горшок на каждый пердеж
@pytest.fixture(scope="class") # Один горшок на всю семью (класс)
@pytest.fixture(scope="module") # Один сортир на весь подъезд (модуль)
@pytest.fixture(scope="session") # Одна выгребная яма на всю деревню (сессию)
Экономия ресурсов — овердохуищная!
Но самое весёлое начинается, когда они друг на друга ссылаются, как алкоголики в подворотне. Одна фикстура может зависеть от другой:
@pytest.fixture
def config():
return {"host": "localhost", "port": 5432}
@pytest.fixture
def db_connection(config): # Смотри-ка, сука, взяла у соседки сахар!
return Database(host=config["host"], port=config["port"])
Pytest сам разберётся, в каком порядке их вызывать, чтобы не получилось, что база данных требует конфиг, которого ещё нет. Умный, блядь, как советский холодильник.
А если хочешь поиздеваться над тестами и прогнать их по всем мыслимым и немыслимым сценариям, есть параметризованные фикстуры. Это как дать дегустатору три сорта водки, а он должен выбрать лучший, но в итоге всё равно свалится под стол.
@pytest.fixture(params=["sqlite", "postgres", "mysql"])
def database(request):
if request.param == "sqlite":
return SQLiteDatabase(":memory:")
elif request.param == "postgres":
return PostgresDatabase("localhost")
# Тест запустится трижды, и каждый раз будет охуевать от новой базы
def test_query(database):
assert database.query("SELECT 1") == 1
И где это всё применяется? Да везде, сука! Подготовить тестовые данные — фикстура. Поднять мок API — фикстура. Настроить окружение, почистить за собой бардак — всё она, хитрая жопа.
А если хочешь, чтобы какая-то фикстура работала автоматом, без твоего ведома, как теща в твоём холодильнике, — положи её в conftest.py и поставь autouse=True.
# conftest.py (фикстуры тут видны всем тестам в папке и ниже)
import pytest
@pytest.fixture(autouse=True) # Автоматически впендюрится в каждый тест
def log_test_start():
print("n--- Test started ---")
yield
print("--- Test finished ---")
Вот и всё, вротберунчик. Фикстуры — это не просто синтаксический сахар, это целый кондитерский цех, который печёт торты для твоих тестов. Главное — не переборщить с зависимостями, а то получится такая паутина, что сам Чиполлино в ней запутается, блядь.