简体   繁体   English

使用pytest使用奇怪的语法测试装饰器

[英]testing decorator with pytest using weird syntax

so I wanted to test a decorator that gives you a coroutine that's primed up (so I don't have to do coroutine.send(None) ). 所以我想测试一个装饰器,该装饰器可以为您提供已预涂的协程(因此,我不必做coroutine.send(None) )。

Details can be found here . 详细信息可以在这里找到。 David Beazley's example) 大卫·比兹利(David Beazley)的例子)

so in conftest.py I created a function wrapper that's a pytest fixture, which gives me a raw coroutine, if that makes sense. 所以在conftest.py中,我创建了一个函数包装器,该包装器是pytest固定装置,如果可以的话,可以给我一个原始的协程。

the reason I am doing this is because pytest will take anything after yield keyword as teardown codes and I don't want that. 我这样做的原因是因为pytest在yield关键字后将任何东西都用作拆卸代码,但我不希望这样做。 so I wrapp up a raw coroutine myself. 所以我自己包装了一个原始的协程。

@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

now in my test file I have a rather simple test: 现在在我的测试文件中,我有一个相当简单的测试:

    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)

ok that's it. 好的,就是这样。 pytest complained: pytest抱怨:

create_coroutine() missing 1 required positional argument: 'pattern' create_coroutine()缺少1个必需的位置参数:“模式”

then I went ahead edited line 2: 然后我继续编辑第2行:

coro_func = create_coroutine_func("python") # match anything has 'python' in it.

now test passed. 现在测试通过了。

now I a bit confused with decorators now. 现在,我现在对装饰感到有些困惑。

So in my example grep takes an argument; 因此,在我的示例中,grep接受了一个参数; when I call my grep function wrapper, I need to give the function wrapper an argument as well although it doesn't take any argument itself? 当我调用grep函数包装器时,我也需要给函数包装器一个参数,尽管它本身不需要任何参数? is this how decorator works? 这是装饰器的工作方式吗?

UPD: As @jacques-kvam pointed out in the comments, when you pass a fixture as an argument into a test function, the return value of the fixture IS the argument's value. UPD:正如@ jacques-kvam在注释中指出的那样,当您将夹具作为参数传递给测试函数时,夹具的返回值就是参数的值。 So in your case, line 2 create_coroutine_func is grep . 因此,在您的情况下,第2行create_coroutine_funcgrep

This misunderstanding of the pytest fixtures is probably the main reason of misuse of the values in the test function itself. pytest固定装置的这种误解可能是滥用测试函数本身中的值的主要原因。

Once this is clear, here is my original answer: 一旦清楚了,这就是我的原始答案:


Here, you call your function on line 2 in create_coroutine_func() . 在这里,您可以在create_coroutine_func()第2行调用函数。 This is why it expects the parameter to be passed. 这就是为什么它期望参数被传递的原因。

What you actually need, if you want to wrap the function into a decorator, is to operate on the function-object itself. 如果要将功能包装到装饰器中,实际上需要对功能对象本身进行操作。 It do not call it, but pass it as a value to the decorator: 它不调用它,而是将其作为值传递给装饰器:

def test_coroutine(create_coroutine_func):
    coro_wrapper = coroutine(create_coroutine_func)
    assert callable(coro_wrapper)
    coro_wrapper("python")

This is how the decorators work: they take one function as an argument and return another (or the same) function as the result. 装饰器就是这样工作的:它们将一个函数作为参数,然后返回另一个(或相同)函数作为结果。


PS: This same test can be written in a more nice syntax: 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")

Note that the decorator usage is inside of the test. 请注意,装饰器的用法在测试内部。 So if anything goes wrong, the test will fail normally, not the pytest's module importing (as it would happen if the decorated function is declared on the module level, which you probably already noticed). 因此,如果发生任何错误,测试将正常失败,而不是pytest的模块导入(因为如果在模块级别上声明了修饰的函数(您可能已经注意到)会发生这种情况)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM