У меня есть следующий блок кода.
@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 вопроса:
- Почему здесь принимаются другие 2 случая?
- Как мне заставить pytest понимать, что нужно запускать только случай
<Function 'test_A[some_A.json-remote]'>
?
Ответ
Чтобы понять, почему pytest включает дополнительные случаи и как добиться желаемого поведения при использовании маркеров, давайте разберем ваш код и саму логику параметризации.
Ответ на вопрос 1: Почему включаются другие случаи?
Когда вы используете pytest.mark.parametrize
, каждый параметр создает комбинацию с другими параметрами. В вашем случае вы имеете две параметризации:
-
project_name
с параметрами:- "default" (с меткой
pytest.mark.defa
) - "remote" (с метками
pytest.mark.remote
иpytest.mark.nightly
)
- "default" (с меткой
spec_file
с параметрами:- "some_A.json" (с меткой
pytest.mark.nightly
) - "some_B.json" (без меток)
- "some_A.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
, есть несколько способов:
- Используйте условия в параметризации: Вы можете вручную фильтровать параметры в
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
- Используйте истину в параметрах: Если вам нужно комбинировать условия, рекомендуется добавить проверку в сам тест.
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]'
, как вы и ожидали.