如何使pytest灯具与装饰功能一起使用?

jck*_*jck 31 python unit-testing decorator pytest

当我修饰具有fixture作为参数的测试函数时,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
Run Code Online (Sandbox Code Playgroud)

在这个简单的例子中,我收到以下错误:

TypeError: test_something() takes exactly 1 argument (0 given).
Run Code Online (Sandbox Code Playgroud)

有没有办法解决这个问题,最好不要过多地修改装饰器?(因为装饰器也在测试代码之外使用.)

jck*_*jck 34

它看起来像functools.wraps不能很好地完成这项工作,所以它打破了py.test的内省.

使用装饰器包创建装饰似乎可以解决问题.

import decorator

def deco(func):
    def wrapper(func, *args, **kwargs):
        return func(*args, **kwargs)
    return decorator.decorator(wrapper, func)
Run Code Online (Sandbox Code Playgroud)

  • 知道pytest依赖于装饰器会很有用,所以你不需要引入任何新的依赖. (4认同)
  • 为什么你的答案中有两种“func”用法?这是故意的吗? (2认同)

fal*_*tru 7

夹具功能取决于测试功能签名。

如果您可以按如下方式更改包装签名,它将起作用。

def deco(func):
    @functools.wraps(func)
    def wrapper(x):
        return func(x)
    return wrapper
Run Code Online (Sandbox Code Playgroud)

如果你不能改变它,那就再做一个装饰器:

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
Run Code Online (Sandbox Code Playgroud)

test_somthing用以下内容装饰deco_x

@deco_x
@deco
def test_something(x):
    assert x == 0
Run Code Online (Sandbox Code Playgroud)

  • 如果我想将参数传递给装饰器本身该怎么办。例如@deco_x(2) (4认同)