Как добавить маркеры pytest к нескольким параметризациям

Вопросы и ответы

У меня есть следующий блок кода.

    @pytest.mark.parametrize("project_name", [
        pytest.param("default", marks=pytest.mark.defa),
        pytest.param("remote", marks=[pytest.mark.remote, pytest.mark.nightly])
     ])
    @pytest.mark.parametrize("spec_file", [
        pytest.param("some_A.json", marks=pytest.mark.nightly),
        pytest.param("some_B.json")
    ])
    def test_A(self, project_name, spec_file):
        assert 1==1

Если я попытаюсь собрать/запустить маркер nightly с помощью команды pytest -m nightly --collect-only -qq <path_to_test_file>, я получаю следующий вывод

        <Function 'test_A[some_A.json-remote]'>
        <Function 'test_A[some_A.json-default]'>
        <Function 'test_A[some_B.json-remote]'>

Я ожидал, что соберутся или запустятся только параметры <Function 'test_A[some_A.json-remote]'>. У меня есть 2 вопроса:

  1. Почему здесь принимаются другие 2 случая?
  2. Как мне заставить pytest понимать, что нужно запускать только случай <Function 'test_A[some_A.json-remote]'>?

Ответ

Чтобы понять, почему pytest включает дополнительные случаи и как добиться желаемого поведения при использовании маркеров, давайте разберем ваш код и саму логику параметризации.

Ответ на вопрос 1: Почему включаются другие случаи?

Когда вы используете pytest.mark.parametrize, каждый параметр создает комбинацию с другими параметрами. В вашем случае вы имеете две параметризации:

  1. project_name с параметрами:

    • "default" (с меткой pytest.mark.defa)
    • "remote" (с метками pytest.mark.remote и pytest.mark.nightly)
  2. spec_file с параметрами:
    • "some_A.json" (с меткой pytest.mark.nightly)
    • "some_B.json" (без меток)

Таким образом, pytest создает следующие комбинации:

  • "default" с "some_A.json" (не имеет меток nightly)
  • "default" с "some_B.json" (не имеет меток nightly)
  • "remote" с "some_A.json" (с меткой nightly)
  • "remote" с "some_B.json" (с меткой remote, но не nightly)

Это приводит к тому, что pytest видит все комбинации и не фильтрует их по меткам, кроме тех, которые были непосредственно назначены в параметризации.

Ответ на вопрос 2: Как сделать так, чтобы pytest выполнял только нужные комбинации?

Чтобы решить проблему и заставить pytest выполнять только те случаи, которые действительно помечены меткой nightly, есть несколько способов:

  1. Используйте условия в параметризации: Вы можете вручную фильтровать параметры в pytest.mark.parametrize, чтобы включить только те, которые имеют необходимые метки.
import pytest

@pytest.mark.parametrize("project_name", [
    pytest.param("remote", marks=[pytest.mark.remote, pytest.mark.nightly])
])
@pytest.mark.parametrize("spec_file", [
    pytest.param("some_A.json", marks=pytest.mark.nightly)
])
def test_A(project_name, spec_file):
    assert 1 == 1
  1. Используйте истину в параметрах: Если вам нужно комбинировать условия, рекомендуется добавить проверку в сам тест.
import pytest

@pytest.mark.parametrize("project_name", [
    pytest.param("default", marks=pytest.mark.defa),
    pytest.param("remote", marks=[pytest.mark.remote, pytest.mark.nightly])
])
@pytest.mark.parametrize("spec_file", [
    pytest.param("some_A.json", marks=pytest.mark.nightly),
    pytest.param("some_B.json")
])
def test_A(project_name, spec_file):
    if pytest.mark.nightly in project_name or pytest.mark.nightly in spec_file:
        assert 1 == 1

Этот подход позволит вам точно контролировать, какие комбинации собираются тестом.

Например, как можно запускать тесты с метками

Теперь, когда параметры правильно настроены, вы можете запустить тесты с метками следующим образом:

pytest -m nightly <path_to_test_file>

Это должно дать вам только Function 'test_A[some_A.json-remote]', как вы и ожидали.

Оцените материал
Добавить комментарий

Капча загружается...