Сообщить об ошибке.

Параметризованные фикстуры pytest в Python

Содержание:


Передача параметров (params) в фикстуру pytest.

В фикстуры можно передавать параметры для неоднократно выполнения тестов, использующих эти фикстуры. Обычно повторно запускаемые тестовые функции не зависят друг от друга. И в этом случае параметризация фикстур помогает писать исчерпывающие функциональные тесты для компонентов, которые сами по себе могут быть сконфигурированы разными способами.

import pytest
import smtplib

# аргумент `params` отвечает за передачу нескольких параметров
@pytest.fixture(params=["smtp.gmail.com", "mail.python.org"])
def smtp_connection(request):
    # request.param читает параметры по одному за раз
    connect = smtplib.SMTP(request.param, 587, timeout=5)
    print(f"Соединение с {request.param} открыто")
    yield connect
    connect.close()
    print(f"Соединение с {request.param} закрыто")

def test_ehlo(smtp_connection):
    print("Тест начался")
    response, msg = smtp_connection.ehlo()
    assert response == 250
    print("Тест завершился")

Аргумент params в декораторе @pytest.fixture() принимает список параметров, для каждого из которых фикстура будет выполняться и получать значение через request.param.

Если запустить код командой $ pytest -v -s test.py, то будет виден весь вывод функции print(), и то, что тестовая функция была выполнена дважды, сначала с одним, потом с другим объектом connect.

Для каждого значения параметра фикстуры pytest сгенерирует ID-строку, которая его идентифицирует. Можно использовать эти ID для запуска отдельного варианта теста (смотрите Как запускать тесты с модулем pytest) . Если запустить $ pytest --collect-only test.py, то можно увидеть все сгенерированные ID-строки.

<Module test.py>
  <Function test_ehlo[smtp.gmail.com]>
  <Function test_ehlo[mail.python.org]>

Использование маркеров для передачи данных в фикстуру.

Используя объект запроса request, фикстура также может получить доступ к пользовательским маркерам, которые применяются к тестовой функции. Такое поведение может быть полезно для передачи данных в фикстуру из теста:

import pytest

@pytest.fixture
def fixt(request):
    # Считываем данные маркета с данными, примененного к тесту
    marker = request.node.get_closest_marker("fixt_data")
    if marker is None:
        # Каким-то образом обработать отсутствующий маркер...
        data = None
    else:
        data = marker.args[0]

    # Делаем что-то с данными и возвращаем
    return data

# Маркер передает данные тестовой функции
@pytest.mark.fixt_data(42)
# функция принимает фикстуру `fixt`
def test_fixt(fixt):
    assert fixt == 42

Маркировка передаваемых значений параметров в фикстуру.

Для маркировки значений параметров параметризованных фикстур можно использовать функцию pytest.param() точно так же, как и с @pytest.mark.parametrize.

Пример:

import pytest

@pytest.fixture(params=[0, 1, pytest.param(2, marks=pytest.mark.skip)])
def data_set(request):
    return request.param

def test_data(data_set):
    pass

При выполнении этого теста вызов data_set() со значением 2 будет пропущен (skipped).

Функция pytest.param(*values, id, marks).

Функция pytest.param() позволяет указать наряду с передаваемыми значениями *values дополнительные параметры (id, marks) в вызовах @pytest.mark.parametrize или при передачи параметров (params) в фикстуру pytest.

Принимаемые аргументы:

  • values: кортеж значений передаваемых параметров.
  • marks: необязательная отдельная метка или список меток, которые будут применены к этим параметрам.
  • id: необязательная строка, представляющая идентификатор, который нужно присвоить этим параметрам (применяется для выборочного запуска при тестировании).

Пример:

@pytest.mark.parametrize(
    "test_input,expected",
    [("3+5", 8), pytest.param("6*9", 42, marks=pytest.mark.xfail),],
)
def test_eval(test_input, expected):
    assert eval(test_input) == expected