2013-10-27 3 views
22

py.test, похоже, терпит неудачу, когда я украшаю тестовые функции, у которых есть арматура в качестве аргумента.Как сделать pytest светильники работать с украшенными функциями?

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' в Python 3.6. Ошибка в 2.7 – Anentropic

ответ

20

Похоже, что functools.wraps не делает работу достаточно хорошо, поэтому она прерывает интроспекцию py.test.

Создание декоратора с использованием пакета decorator, кажется, делает трюк.

import decorator 

def deco(func): 
    def wrapper(func, *args, **kwargs): 
     return func(*args, **kwargs) 
    return decorator.decorator(wrapper, func) 
+0

Может быть полезно знать, что pytest зависит от декоратора, поэтому вам не нужно затягивать какую-либо новую зависимость. – zneak

4

Характеристика приспособления зависит от сигнатуры тестовой функции.

Если вы можете изменить подпись обертки следующим образом, она будет работать.

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