#pytest #parametrized-testing
#python #pytest #параметризованный-тестирование
Вопрос:
У меня есть тест pytest, который проверяет несколько входных данных для двух разных баз данных. я делаю это, используя параметризованную метку дважды:
@pytest.mark.parametrize(
"input_type",
[
pytest.param("input_1"),
pytest.param("input_2"),
],
)
@pytest.mark.parametrize(
"db_type",
[
pytest.param("db_type_1"),
pytest.param("db_type_2"),
],
)
То, что я испытываю, происходит только при запуске input_1
db_type_2
(например), когда тест завершается неудачей из-за ошибки
, но выполняется один и тот же ввод с разными проходами БД.
Я хочу пометить только input_1
db_type_2
комбинацию and как xfail, в то время как все остальные комбинации не должны быть помечены как xfail.
Я не могу найти, как это сделать.
Если маркировка db_type_2
как xfail:
@pytest.mark.parametrize(
"db_type",
[
pytest.param("db_type_1"),
pytest.param("db_type_2", marks=pytest.mark.xfail)
],
)
все входные данные будут xfailed, и это не то поведение, которое я ищу.
Может ли кто-нибудь помочь мне с этим?
Комментарии:
1. Если вы все еще рядом, теперь вы можете принять один из ответов.
Ответ №1:
Вы не можете пометить тест на основе полного набора аргументов в pytest.mark.parametrize
/ pytest.param
, информации о других аргументах просто еще нет. Обычно я переношу постобработку параметров теста в отдельный инструмент, который затем может изменять тест на основе полного набора тестовых аргументов. Пример:
@pytest.mark.parametrize('x', range(10))
@pytest.mark.parametrize('y', range(20))
def test_spam(x, y):
assert False
Всего у нас 200 тестов; предположим, мы хотим xfail
протестировать для x=3
, y=15
и x=8
, y=1
. Мы добавляем новое приспособление xfail_selected_spams
, которое получает доступ к обоим x
и y
перед test_spam
запуском и xfail
при необходимости добавляет маркер в тестовый экземпляр:
@pytest.fixture
def xfail_selected_spams(request):
x = request.getfixturevalue('x')
y = request.getfixturevalue('y')
allowed_failures = [
(3, 15), (8, 1),
]
if (x, y) in allowed_failures:
request.node.add_marker(pytest.mark.xfail(reason='TODO'))
Чтобы зарегистрировать приспособление, используйте pytest.mark.usefixtures
:
@pytest.mark.parametrize('x', range(10))
@pytest.mark.parametrize('y', range(20))
@pytest.mark.usefixtures('xfail_selected_spams')
def test_spam(x, y):
assert False
При запуске тестов сейчас мы получим 198 failed, 2 xfailed
результаты, поскольку ожидается, что два выбранных теста завершатся неудачей.
Ответ №2:
Вы могли бы создать функцию, которая будет выполняться во время сбора тестов и обрабатывает параметризацию и xfail
метку на основе данных
def data_source():
input_types = ['input_1', 'input_2']
db_types = ['db_type_1', 'db_type_2']
for tup in itertools.product(input_types, db_types):
marks = []
if tup == ('input_1', 'db_type_2'):
marks.append(pytest.mark.xfail(reason=f'{tup}'))
yield pytest.param(tup, marks=marks)
@pytest.mark.parametrize('test_data', data_source())
def test_example(self, test_data):
assert test_data != ('input_1', 'db_type_2')
itertools.product
позволяет добавить еще один список входных данных без изменения какой-либо другой части кода, за исключением if
условия для разрешенных входных данных.
Комментарии:
1. Спасибо за хороший ответ. Я мог назначить награду только один раз. Я немного предпочитаю другой ответ, потому что он сохраняет параметры и их значения близкими к определению теста, перенося только ожидаемые комбинации сбоев во внешнюю функцию.