How do I make pytest fixtures work with decorated functions?
15,215
Solution 1
It looks like functools.wraps does not do the job well enough, so it breaks py.test's introspection.
Creating the decorator using the decorator package seems to do the trick.
import decorator
def deco(func):
def wrapper(func, *args, **kwargs):
return func(*args, **kwargs)
return decorator.decorator(wrapper, func)
Solution 2
Fixture feature depends on test function signature.
If you can change wrapper signature as follow, it will works.
def deco(func):
@functools.wraps(func)
def wrapper(x):
return func(x)
return wrapper
If you can't change it, make another decorator:
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
And decorate test_somthing
with deco_x
:
@deco_x
@deco
def test_something(x):
assert x == 0
Author by
jck
Updated on June 25, 2022Comments
-
jck about 2 years
py.test seems to fail when I decorate test functions which has a fixture as an argument.
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
In this simple example, I get the following error:
TypeError: test_something() takes exactly 1 argument (0 given).
Is there a way to fix this, preferably without modifying the decorator too much? (Since the decorator is used outside testing code too.)
-
zneak over 6 yearsIt could be useful to know that pytest depends on decorator, so you don't need to pull in any new dependency.
-
falsetru over 6 years@KjeldFlarup, How about jck's answer ?
-
Steven over 5 yearsAwesome! Great job
-
user1065000 about 4 yearsWhat to do if I want to pass an argument to decorator itself. e.g. @deco_x(2)
-
user1065000 about 4 yearsHow shall we handle passing an argument to deco when using this e.g. @deco(3)
-
joel about 4 yearswhy are there two uses of
func
in your answer? is that intentional? -
paveldroo almost 3 years@joel it seems intentional. Without second
func
decorator doesn't work, though even PyCharm warns about shadowing name from outer scope.