结合py.测试和trio/curi

2024-04-27 23:01:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我将结合pytest和trio(或者curio,如果这更容易的话),也就是说,将我的测试用例作为协程函数来编写。通过在conftest.py中声明一个自定义测试运行器,这相对容易实现:

    @pytest.mark.tryfirst
    def pytest_pyfunc_call(pyfuncitem):
        '''If item is a coroutine function, run it under trio'''

        if not inspect.iscoroutinefunction(pyfuncitem.obj):
            return

        kernel = trio.Kernel()
        funcargs = pyfuncitem.funcargs
        testargs = {arg: funcargs[arg]
                    for arg in pyfuncitem._fixtureinfo.argnames}
        try:
            kernel.run(functools.partial(pyfuncitem.obj, **testargs))
        finally:
            kernel.run(shutdown=True)

        return True

这样我就可以编写这样的测试用例:

^{2}$

但这是一个样板。在非异步代码中,我会将其分解到fixture中:

@pytest.yield_fixture()
def mock_server():
    server = MockServer()
    thread = threading.Thread(server.serve)
    thread.start()

    try:
        yield server
    finally:
        server.please_terminate()
        thread.join()
        server.server_close()

def test_something(mock_server):
   # do the test..

有没有一种方法可以在trio中实现同样的功能,即实现异步fixture?理想情况下,我只写:

async def test_something(mock_server):
   # do the test..

Tags: runtestobjtrioserverpytestdefarg
1条回答
网友
1楼 · 发布于 2024-04-27 23:01:08

编辑:下面的答案现在基本上是不相关的-改为使用pytest trio并跟随instructions in its manual。在


您的示例pytest_pyfunc_call代码不起作用,因为它是trio和curio的混合体:-)。对于trio,有一个decorator trio.testing.trio_test可以用来标记单个测试(比如如果您使用的是经典的unittest或其他东西),所以编写pytest插件函数的最简单方法就是将其应用于每个异步测试:

from trio.testing import trio_test

@pytest.mark.tryfirst
def pytest_pyfunc_call(pyfuncitem):
    if inspect.iscoroutine(pyfuncitem.obj):
        # Apply the @trio_test decorator
        pyfuncitem.obj = trio_test(pyfuncitem.obj)

如果你好奇,这基本上相当于:

^{pr2}$

不管怎样,这并不能解决你的固定装置问题,因为你需要更多的东西。在

相关问题 更多 >