Ответ
В PyTest yield и return используются в фикстурах для передачи данных в тест, но с фундаментальным отличием в возможности выполнить код очистки (teardown) после завершения теста.
Фикстура с return
- Передаёт значение в тест и завершает работу.
- Не предоставляет встроенного механизма для очистки. Если ресурс нужно закрыть, это делается отдельно (например, в финальной фазе теста или с помощью
request.addfinalizer).
Фикстура с yield
- Работает как генератор. Код до
yieldвыполняется как установка (setup), а код послеyield— как очистка (teardown). - Очистка выполняется гарантированно, даже если тест упал с ошибкой (assertion или exception).
- Это идеальный способ для работы с ресурсами, требующими закрытия (файлы, соединения с БД, браузеры).
Практический пример с временным файлом:
import pytest
import os
# Фикстура с yield (рекомендуемый способ для ресурсов)
@pytest.fixture
def temp_config_file():
# SETUP: Создаём временный файл перед тестом
file_path = "/tmp/test_config.yaml"
with open(file_path, 'w') as f:
f.write("test_key: test_value")
print("Файл создан")
yield file_path # Передаём путь к файлу в тест
# TEARDOWN: Удаляем файл после теста (выполнится всегда)
os.remove(file_path)
print("Файл удалён")
# Фикстура с return и addfinalizer (альтернативный способ)
@pytest.fixture
def temp_config_file_v2(request):
file_path = "/tmp/test_config_v2.yaml"
with open(file_path, 'w') as f:
f.write("test_key: test_value")
print("Файл v2 создан")
def cleanup():
os.remove(file_path)
print("Файл v2 удалён")
request.addfinalizer(cleanup) # Регистрируем функцию очистки
return file_path # Передаём путь
# Тест использует фикстуру
def test_read_config(temp_config_file):
# В тест передан file_path
with open(temp_config_file) as f:
content = f.read()
assert "test_key" in content
# После этого теста PyTest автоматически выполнит os.remove(file_path)
Вывод: Для управления жизненным циклом ресурсов (открыть/закрыть) всегда используйте фикстуры с yield. return подходит для простых данных, не требующих очистки.
Ответ 18+ 🔞
А, ну вот, опять про эти фикстуры в PyTest спрашивают! Ебать мои старые костыли, каждый раз одно и то же объясняю. Слушай сюда, сейчас разложу по полочкам, чтобы даже мартышлюшка поняла.
В общем, есть две штуки — yield и return. И разница между ними, чувак, как между "взял попить" и "взял попить, а потом поставил стакан обратно в шкаф, а не оставил на столе, как последний распиздяй".
Фикстура с return — это просто, блядь, передал значение в тест и пошёл на хуй. Всё. Точка. Очистки никакой нет. Если ты файл открыл или базу подключил — сам потом закрывай, терпения ебать ноль, чтобы за тобой убирали.
Фикстура с yield — это уже хитрая жопа. Она работает как генератор. Всё, что до yield — это настройка (setup), типа "открыл файл, подключился к базе". Потом yield передаёт управление тесту вместе с данными. А ВСЁ, ЧТО ПОСЛЕ yield — это гарантированная уборка (teardown). Даже если тест упал с пиздец-ошибкой, даже если ты сам от себя охуел от результата — очистка выполнится. Это как договор с дьяволом, только полезный.
Простой пример, чтобы не ебать копать: Допустим, тебе нужен временный файл для теста.
С return — это пиздопроебибна. Создал файл, вернул путь, а удалять его — это уже твои проблемы. Забудешь — диск засрется.
А вот с yield — красота, ёпта. Создал файл, yieldнул путь тесту, тест отработал (или не отработал), и ПОТОМ, автоматически, файл удаляется. Волнение ебать — ноль. Всё чисто.
Смотри, как это выглядит в коде. Блоки кода не трогаю, они святые:
import pytest
import os
# Вот фикстура с yield — правильный путь, чувак
@pytest.fixture
def temp_config_file():
# SETUP: Делаем файл перед тестом
file_path = "/tmp/test_config.yaml"
with open(file_path, 'w') as f:
f.write("test_key: test_value")
print("Файл создан")
yield file_path # Отдаём путь тесту и как бы замираем
# TEARDOWN: А вот это выполнится ПОСЛЕ теста в любом случае!
os.remove(file_path)
print("Файл удалён")
# А это фикстура с return и костылём в виде addfinalizer
@pytest.fixture
def temp_config_file_v2(request):
file_path = "/tmp/test_config_v2.yaml"
with open(file_path, 'w') as f:
f.write("test_key: test_value")
print("Файл v2 создан")
def cleanup(): # Функция-уборщица
os.remove(file_path)
print("Файл v2 удалён")
request.addfinalizer(cleanup) # Регистрируем уборщицу
return file_path # И возвращаем путь
# Сам тест
def test_read_config(temp_config_file):
# Тут у нас уже лежит file_path
with open(temp_config_file) as f:
content = f.read()
assert "test_key" in content
# И после assert PyTest сам вызовет os.remove(file_path) из фикстуры!
Итог, блядь: Если тебе нужно просто передать в тест цифру, строку или список — return и да похуй. Но если работаешь с чем-то, что нужно ОБЯЗАТЕЛЬНО закрыть, освободить, удалить, отключить — это твой верный друг yield. Не усложняй себе жизнь, используй правильный инструмент.