Как создать фикстуру в `pytest`?

Фикстуры в pytest создаются с помощью декоратора @pytest.fixture над функцией. Эта функция определяет контекст для тестов, например, подготовка данных, подключение к БД или моки. Фикстура может возвращать значения, которые будут доступны тестам, использующим её в качестве аргумента.

Пример:

  import pytest

  @pytest.fixture
  def my_fixture():
      # Здесь код для подготовки данных или ресурсов
      return "Some data"

  def test_using_fixture(my_fixture):
      assert my_fixture == "Some data"
  

В `pytest` фикстуры создаются с помощью декоратора `@pytest.fixture`. Фикстура - это функция, которая предоставляет предопределенное состояние или ресурсы для тестов.

Вот основные моменты:

  1. Импортируйте `pytest`: Начните с импорта модуля `pytest`.
  2. Используйте декоратор `@pytest.fixture`: Определите функцию и добавьте декоратор `@pytest.fixture` перед ней. Имя функции станет именем фикстуры.
  3. Возвращайте значение: Фикстура возвращает данные или объект, который будет использоваться в тестах.
  4. Используйте фикстуру в тесте: Укажите имя фикстуры как аргумент тестовой функции. `pytest` автоматически выполнит фикстуру и передаст ее возвращаемое значение в тестовую функцию.

Пример:


import pytest

@pytest.fixture
def sample_data():
  """
  Эта фикстура предоставляет пример данных.
  """
  data = {"name": "Alice", "age": 30}
  return data

def test_sample_data(sample_data):
  """
  Этот тест использует фикстуру sample_data.
  """
  assert sample_data["name"] == "Alice"
  assert sample_data["age"] == 30
  

Объяснение:

  • `@pytest.fixture` помечает функцию `sample_data` как фикстуру.
  • Функция `sample_data` создает словарь `data` и возвращает его.
  • В функции `test_sample_data`, `sample_data` указана как аргумент. `pytest` автоматически выполнит фикстуру `sample_data` и передаст возвращенный словарь в качестве аргумента в `test_sample_data`.
  • Тест проверяет, что данные, предоставленные фикстурой, соответствуют ожидаемым значениям.

Область видимости (scope):

Фикстуры могут иметь различную область видимости, определяющую, как часто они будут выполняться. Область видимости задается с помощью параметра `scope` в декораторе `@pytest.fixture`. Распространенные значения:

  • `function` (по умолчанию): Фикстура выполняется один раз для каждого теста.
  • `class`: Фикстура выполняется один раз для каждого класса.
  • `module`: Фикстура выполняется один раз для каждого модуля.
  • `session`: Фикстура выполняется один раз для всего сеанса тестирования.

Пример с областью видимости:


import pytest

@pytest.fixture(scope="module")
def db_connection():
  """
  Эта фикстура предоставляет подключение к базе данных,
  которое используется всеми тестами в модуле.
  """
  connection = connect_to_db()  # Предполагаем, что connect_to_db() возвращает подключение
  yield connection  # Используем yield для финализации
  connection.close() # Закрываем соединение после выполнения всех тестов в модуле
  

Финализация (teardown):

Фикстуры могут выполнять очистку или финализацию после выполнения тестов, которые их используют. Это часто делается с помощью ключевого слова `yield`.

Пример финализации:


import pytest

@pytest.fixture
def temp_file():
  """
  Эта фикстура создает временный файл и удаляет его после теста.
  """
  import tempfile
  temp_file = tempfile.NamedTemporaryFile(delete=False)
  file_path = temp_file.name
  yield file_path
  # Код ниже выполняется после завершения теста, использующего эту фикстуру
  import os
  os.remove(file_path)
  

В этом примере, фикстура создает временный файл. `yield file_path` возвращает путь к файлу для использования в тесте. После того, как тест завершится, выполняется код после `yield`, который удаляет временный файл.

Использование `request` object:

Объект `request` (передается фикстуре как аргумент) предоставляет информацию о контексте выполнения фикстуры, такую как модуль, класс, или функция, которая запрашивает фикстуру. Это может быть полезно для создания параметризованных фикстур или выполнения специфичных задач в зависимости от контекста.

Пример с использованием `request`:


import pytest

@pytest.fixture
def log_file(request):
  """
  Эта фикстура создает лог файл, имя которого зависит от имени теста.
  """
  test_name = request.node.name
  log_file_path = f"log_{test_name}.txt"
  with open(log_file_path, "w") as f:
    yield log_file_path
  # Удаляем лог файл после теста
  import os
  os.remove(log_file_path)
  
0