Как сделать pytest fixtures работать с украшенными функциями?
py.test, похоже, терпит неудачу, когда я украшаю тестовые функции, у которых есть арматура в качестве аргумента.
def deco(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@pytest.fixture
def x():
return 0
@deco
def test_something(x):
assert x == 0
В этом простом примере я получаю следующую ошибку:
TypeError: test_something() takes exactly 1 argument (0 given).
Есть ли способ исправить это, желательно, не слишком сильно изменив декоратор? (Так как декоратор используется вне кода тестирования тоже.)
Ответы
Ответ 1
Похоже, что functools.wraps не делает работу достаточно хорошо, поэтому она прерывает интроспекцию py.test.
Создание декоратора с помощью пакета decorator кажется трюком.
import decorator
def deco(func):
def wrapper(func, *args, **kwargs):
return func(*args, **kwargs)
return decorator.decorator(wrapper, func)
Ответ 2
Функция Fixture зависит от сигнатуры тестовой функции.
Если вы можете изменить подпись обертки следующим образом, она будет работать.
def deco(func):
@functools.wraps(func)
def wrapper(x):
return func(x)
return wrapper
Если вы не можете изменить его, сделайте еще один декоратор:
def deco(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
def deco_x(func):
@functools.wraps(func)
def wrapper(x):
return func(x)
return wrapper
И украсьте test_somthing
с помощью deco_x
:
@deco_x
@deco
def test_something(x):
assert x == 0