Ответ
Да, постоянно использую контекстные менеджеры в автотестах на Python для гарантированного управления ресурсами и состояниями. Это критически важно для создания стабильных и изолированных тестов.
Основные сценарии применения в тестировании:
-
Работа с временными файлами и данными: Использую
tempfile.TemporaryDirectoryиtempfile.NamedTemporaryFile, чтобы файлы удалялись автоматически после теста, даже если он упал.import tempfile import json def test_data_is_saved_correctly(): with tempfile.NamedTemporaryFile(mode='w+', suffix='.json', delete=False) as tmp: # Тест записывает данные во временный файл json.dump({"test": "data"}, tmp) tmp.flush() # ... здесь код, который читает и проверяет файл # Файл автоматически удаляется после выхода из блока `with` -
Мокирование и патчинг (с помощью
unittest.mock): Контекстный менеджерpatchпозволяет временно подменить объект только на время выполнения теста.from unittest.mock import patch def test_external_api_call(): with patch('requests.get') as mock_get: # Настраиваем мок на время этого теста mock_get.return_value.status_code = 200 mock_get.return_value.json.return_value = {"ok": true} # Вызов тестируемой функции, которая использует requests.get result = function_under_test() assert result is True # После выхода из `with` оригинальный requests.get восстанавливается -
Управление соединениями с БД или внешними сервисами: Пишу собственные контекстные менеджеры или использую предоставляемые фреймворками (например, в Django/Pytest) для работы с тестовыми транзакциями, чтобы не засорять базу данных.
-
Замер времени выполнения (для performance-тестов):
import time from contextlib import contextmanager @contextmanager def timer(): start = time.perf_counter() yield end = time.perf_counter() print(f"Time elapsed: {end - start:.4f} seconds") def test_function_performance(): with timer(): # Выполняем операцию, время которой хотим замерить heavy_operation()
Использование with гарантирует, что ресурсы будут освобождены, а состояние окружения — восстановлено, что делает тесты более надежными и идемпотентными.
Ответ 18+ 🔞
А, ну это же классика, ебать мои старые костыли! Контекстные менеджеры в тестах — это как надежный друг, который всегда прикроет твою кривую жопу. Без них — просто пиздец, а не тесты, один сплошной распиздяй в коде.
Смотри, в чём тут соль. Представь, ты пишешь тест, который создаёт кучу временных файлов. Без with и tempfile ты либо забудешь их удалить, и твой диск превратится в помойку, либо тест упадёт на середине, и файлы так и останутся висеть, как манда с ушами. А с контекстным менеджером — всё чисто, даже если всё пошло по пизде. Выйдешь из блока with — и файлов как не бывало, хоть трава не расти.
import tempfile
import json
def test_data_is_saved_correctly():
with tempfile.NamedTemporaryFile(mode='w+', suffix='.json', delete=False) as tmp:
# Пишем всякую хуйню во временный файл
json.dump({"test": "data"}, tmp)
tmp.flush()
# ... тут проверяем, что всё записалось
# А тут уже файла нет, всё само подмели, красота!
Или вот ещё любимый фокус — мокирование. Ёпта, без patch из unittest.mock вообще никуда. Тебе же не нужно, чтобы твой тест реально лез в интернет или в продовскую базу? Вот и я о том же. Нахуй эти риски.
from unittest.mock import patch
def test_external_api_call():
with patch('requests.get') as mock_get:
# Говорим моку: "Слушай сюда, чувак, на время этого теста ты — requests.get"
mock_get.return_value.status_code = 200
mock_get.return_value.json.return_value = {"ok": true}
# А тут наша функция дергает этот мок, даже не подозревая подмены
result = function_under_test()
assert result is True
# Всё, тест кончился, мок снялся, и никто ничего не заметил. Идеальная операция.
А если тебе нужно что-то своё, хитрожопое? Например, засечь, сколько времени выполняется какая-нибудь тяжёлая хрень? Да запросто, свой контекстный менеджер напишешь за минуту.
import time
from contextlib import contextmanager
@contextmanager
def timer():
start = time.perf_counter()
yield
end = time.perf_counter()
print(f"Time elapsed: {end - start:.4f} seconds")
def test_function_performance():
with timer():
# Запускаем какую-нибудь дохуя сложную операцию
heavy_operation()
# И сразу видим в консоли, не обосралась ли она по времени
Короче, суть в чём. Контекстные менеджеры через with — это гарантия, что какой бы пиздец ни случился в тесте, ресурсы за собой приберут, соединения закроют, а моки снимут. Тесты становятся изолированными, как будто каждый работает в своём пузыре. А это, блядь, самое главное для спокойной жизни. Иначе один кривой тест засрёт состояние для всех остальных, и потом будешь неделю искать, почему всё падает. Доверия к таким тестам — ноль ебать.