Подтвердить что ты не робот

Как сделать 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).

Есть ли способ исправить это, желательно, не слишком сильно изменив декоратор? (Так как декоратор используется вне кода тестирования тоже.)

4b9b3361

Ответ 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