[英]testing decorator with pytest using weird syntax
所以我想测试一个装饰器,该装饰器可以为您提供已预涂的协程(因此,我不必做coroutine.send(None)
)。
详细信息可以在这里找到。 大卫·比兹利(David Beazley)的例子)
所以在conftest.py中,我创建了一个函数包装器,该包装器是pytest固定装置,如果可以的话,可以给我一个原始的协程。
我这样做的原因是因为pytest在yield关键字后将任何东西都用作拆卸代码,但我不希望这样做。 所以我自己包装了一个原始的协程。
@pytest.fixture(scope="module")
def create_coroutine_func():
def grep(pattern):
print "Looking for %s" % pattern
while True:
line = (yield)
if pattern in line:
print line
return grep
现在在我的测试文件中,我有一个相当简单的测试:
from something.decorators import *
import pytest
1 def test_coroutine(create_coroutine_func):
2 coro_func = create_coroutine_func()
3 coro_wrapper = coroutine(coro_func)
4
5 assert callable(coro_wrapper)
好的,就是这样。 pytest抱怨:
create_coroutine()缺少1个必需的位置参数:“模式”
然后我继续编辑第2行:
coro_func = create_coroutine_func("python") # match anything has 'python' in it.
现在测试通过了。
现在,我现在对装饰感到有些困惑。
因此,在我的示例中,grep接受了一个参数; 当我调用grep函数包装器时,我也需要给函数包装器一个参数,尽管它本身不需要任何参数? 这是装饰器的工作方式吗?
UPD:正如@ jacques-kvam在注释中指出的那样,当您将夹具作为参数传递给测试函数时,夹具的返回值就是参数的值。 因此,在您的情况下,第2行create_coroutine_func
是grep
。
pytest固定装置的这种误解可能是滥用测试函数本身中的值的主要原因。
一旦清楚了,这就是我的原始答案:
在这里,您可以在create_coroutine_func()
第2行调用函数。 这就是为什么它期望参数被传递的原因。
如果要将功能包装到装饰器中,实际上需要对功能对象本身进行操作。 它不调用它,而是将其作为值传递给装饰器:
def test_coroutine(create_coroutine_func):
coro_wrapper = coroutine(create_coroutine_func)
assert callable(coro_wrapper)
coro_wrapper("python")
装饰器就是这样工作的:它们将一个函数作为参数,然后返回另一个(或相同)函数作为结果。
PS:可以使用更漂亮的语法编写该测试:
from something.decorators import *
import pytest
def test_coroutine(create_coroutine_func):
@coroutine
def grep(pattern):
print "Looking for %s" % pattern
while True:
line = (yield)
if pattern in line:
print line
assert callable(grep)
grep("python")
请注意,装饰器的用法在测试内部。 因此,如果发生任何错误,测试将正常失败,而不是pytest的模块导入(因为如果在模块级别上声明了修饰的函数(您可能已经注意到)会发生这种情况)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.