Ответ
В pytest для управления жизненным циклом ресурсов (например, закрытие соединений с БД, удаление временных файлов) используются фикстуры. Очистка (teardown) реализуется двумя основными способами.
1. Использование yield (рекомендуемый способ)
Это наиболее распространенный и читаемый подход. Код до yield является setup-частью, а код после yield — teardown-частью, которая гарантированно выполнится после завершения теста.
Пример с временным файлом:
import pytest
import os
@pytest.fixture
def temp_file():
# Setup: создаем файл
file_path = "test_temp_file.txt"
with open(file_path, "w") as f:
f.write("hello")
yield file_path # Передаем ресурс в тест
# Teardown: удаляем файл
print(f"nCleaning up {file_path}...")
os.remove(file_path)
def test_read_temp_file(temp_file):
with open(temp_file, "r") as f:
assert f.read() == "hello"
2. Использование request.addfinalizer
Этот метод позволяет динамически добавлять функции для очистки. Он полезен в более сложных сценариях, например, когда нужно зарегистрировать несколько финализаторов.
Пример:
import pytest
class DatabaseConnection:
def __init__(self, name):
self.name = name
self.is_open = True
print(f"nDB '{self.name}' connection opened.")
def close(self):
self.is_open = False
print(f"nDB '{self.name}' connection closed.")
@pytest.fixture
def db_conn(request):
conn = DatabaseConnection("main_db")
# Регистрируем функцию, которая будет вызвана для очистки
request.addfinalizer(conn.close)
return conn
def test_db_operations(db_conn):
assert db_conn.is_open
Ключевое различие: yield — это синтаксический сахар, который более нагляден для простого сценария "setup/teardown". addfinalizer предоставляет больше гибкости, но немного усложняет код.