Конфликт поздней привязки с модулем Pytest

#python #testing #iteration #pytest #late-binding

Вопрос:

Я пытаюсь pytest перебирать функции, проблема поздней привязки заставляет pytest применять тест только к последней функции.
Для упрощенного примера я создал следующий test.py файл:

 import pytest   def func_1(x):  return (x 10)   def func_2(y):  return (y-10)   func_1_test_cases = {'func_1': (10, 20)} func_2_test_cases = {'func_2': (10, 0)}  # Iterating over the functions  for func in ['func_1', 'func_2']:  @pytest.mark.parametrize('param, expected',  globals()[func   '_test_cases'].values(),  ids=list(globals()[func    '_test_cases'].keys()))  def test(param, expected):  eval(func '(param) == expected')  

Я прочитал больше о проблеме поздней привязки и о практических предложениях, таких как:

 def test(param, expected, func=func):  eval(func '(param) == expected')  

при использовании команды: pytest test.py -v
pytest отчеты, собирающие только последнюю функцию в списке( func_2 ):

плагины: тайм-аут-1.4.2, anyio-2.2.0, pudb-0.7.0 собрано 1 штука

1.py::тест[ func_2 ] ПРОЙДЕНО [100%]

============================================================================= 1 прошло за 0,01 с =============================================================================

func_1 никогда не собиралось
, похоже, проблема поздней привязки сложнее при использовании pytest . Я ожидаю pytest , что отчет соберет две функции и вернет их статус. Мне действительно нужно разобраться с этим.

Ответ №1:

Это не дает прямого ответа на ваш вопрос об определении нескольких тестов с одинаковым именем, но для конкретного примера, который вы опубликовали, было бы намного проще включить саму функцию в качестве одного из параметров теста:

 import pytest  def func_1(x):  return (x 10)  def func_2(y):  return (y-10)  @pytest.mark.parametrize(  'func,param,expected', [  pytest.param(func_1, 10, 20, id='func_1'),  pytest.param(func_2, 10, 0, id='func_2'),  ], ) def test(func, param, expected):  assert func(param) == expected  

Просто предупреждаю: у вашей тестовой функции нет assert , поэтому она пройдет независимо от того, является ли eval(func '(param) == expected') она истинной или ложной.

Комментарии:

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

Ответ №2:

Вдохновленный ответом Кейла, я считаю, что нет хорошего способа обойти pytest parametize декоратора (надеюсь, кто-нибудь поправит меня, если я ошибаюсь).
Единственное практическое решение-включить идентификаторы функций в список параметров.
Вот измененный код, близкий к тому, что я хотел.

 import pytest   def func_1(x):  return (x 10)   def func_2(y):  return (y-10)  func_test_cases = {'func_1': (10, 20, 'func_1'), 'func_2': (10, 3, 'func_2')}   @pytest.mark.parametrize('param, expected, func',  func_test_cases.values(), ids=func_test_cases.keys()) def test(param, expected, func):  assert eval(func '(param) == expected')