python_测试_异步库插件asyncio

2024/04/14 posted in  开发技术

在python的测试中,如果实际的代码中有异步的代码,如果单纯的调用代码是会出现报错的问题。
需要在测试代码中添加插件pytest-asyncio,这是一个专注于进行异步测试的pytest的插件。

1 安装

根据官网的连接:pytest-asyncio · PyPI
在终端下载对应的库: $ pip install pytest-asyncio
在测试代码方法上添加注解: @@pytest.mark.asyncio

2 使用

具体的使用办法可以参见以下代码:

@pytest.mark.asyncio
async def test_some_asyncio_code():
    res = await library.do_something()
    assert b"expected result" == res

3 案例

在不同的测试场景中,都是能使用到插件的。

3.1 在同一事件loop中运行class中的所有测试

所有测试都可以通过使用pytest.mark.asyncio(scope =“ class”)标记在同一事件循环中运行。通过使用Asyncio标记作为类装饰器,可以很容易地实现这一点。

import asyncio

import pytest

@pytest.mark.asyncio(scope="class")
class TestInOneEventLoopPerClass:
    loop: asyncio.AbstractEventLoop

    async def test_remember_loop(self):
        TestInOneEventLoopPerClass.loop = asyncio.get_running_loop()

    async def test_assert_same_loop(self):
        assert asyncio.get_running_loop() is TestInOneEventLoopPerClass.loop

3.2 在同一事件loop中运行module中的所有测试

所有测试都可以通过使用pytest.mark.asyncio(scope =“ module”)标记在同一事件循环中运行。通过向您的模块添加pytestmark语句可以轻松实现这一点。

import asyncio

import pytest

pytestmark = pytest.mark.asyncio(scope="module")

loop: asyncio.AbstractEventLoop

async def test_remember_loop():
    global loop
    loop = asyncio.get_running_loop()

async def test_assert_same_loop():
    global loop
    assert asyncio.get_running_loop() is loop

3.3 在同一事件loop中运行包装中的所有测试

所有测试都可以通过使用pytest.mark.asyncio(scope =“ package”)标记在同一事件循环中。将以下代码添加到测试包的__init__.py:

请注意,此标记不会传递给子弹中的测试。子包构成了自己的单独包装。

import pytest

pytestmark = pytest.mark.asyncio(scope="package")

3.4 在同一事件循环中进行会话中的所有测试

所有测试都可以通过使用pytest.mark.asyncio(scope =“ session”)标记在同一事件循环中运行。标记所有测试的最简单方法是通过pytest_collection_modifyitems挂钩在您的测试套件的根文件夹中的conftest.py。

import pytest

from pytest_asyncio import is_async_test

def pytest_collection_modifyitems(items):
    pytest_asyncio_tests = (item for item in items if is_async_test(item))
    session_scope_marker = pytest.mark.asyncio(scope="session")
    for async_test in pytest_asyncio_tests:
        async_test.add_marker(session_scope_marker, append=False)

3.5 使用不同的事件循环测试

参数化event_loop_policy灯具参数参数所有异步测试。下面的示例会导致所有异步测试多次运行,一次在固定框架参数中为每个事件循环运行:

import asyncio
from asyncio import DefaultEventLoopPolicy

import pytest

class CustomEventLoopPolicy(DefaultEventLoopPolicy):
    pass

@pytest.fixture(
    scope="session",
    params=(
        CustomEventLoopPolicy(),
        CustomEventLoopPolicy(),
    ),
)
def event_loop_policy(request):
    return request.param

@pytest.mark.asyncio
async def test_uses_custom_event_loop_policy():
    assert isinstance(asyncio.get_event_loop_policy(), CustomEventLoopPolicy)

3.6 events事件

参数化event_loop_policy 参数参数所有异步测试。下面的示例会导致所有异步测试多次运行,一次在固定框架参数中为每个事件循环运行:

如果您只希望测试的一个子集与不同的事件循环一起运行,则可以选择将fixture的范围限制为包、模块或类。

import asyncio
from asyncio import DefaultEventLoopPolicy

import pytest

class CustomEventLoopPolicy(DefaultEventLoopPolicy):
    pass

@pytest.fixture(
    scope="session",
    params=(
        CustomEventLoopPolicy(),
        CustomEventLoopPolicy(),
    ),
)
def event_loop_policy(request):
    return request.param

@pytest.mark.asyncio
async def test_uses_custom_event_loop_policy():
    assert isinstance(asyncio.get_event_loop_policy(), CustomEventLoopPolicy)

3.7 如何对uvloop进行测试

RedeFinig event_loop_policy固定装置将参数所有异步测试。以下示例会导致所有异步测试多次运行,一次在固定夹参数中为每个事件循环进行一次:替换您的conftest.py中的默认事件循环策略:

如果您只希望使用UVloop运行测试的子集,则可以选择将固定装置的范围限制为包装,模块或类。

import pytest
import uvloop

@pytest.fixture(scope="session")
def event_loop_policy():
    return uvloop.EventLoopPolicy()

3.8 如何判断函数是不是为异步

使用pytest_asyncio.is_async_item来确定测试项目是否是异步和由pytest-assyncio管理的。

from pytest_asyncio import is_async_test

def pytest_collection_modifyitems(items):
    for item in items:
        if is_async_test(item):
            pass

4 注意

这个插件也有自己的问题:
它不支持标准联合库的测试类。建议用户使用UnitTest.isolatedAsynciotestcase或异步框架(例如异步)。

本文作者:redtea 红茶的博客
本文链接:https://redtea.top/16964281020029.html
版权声明:本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可,非商业转载及引用请注明出处(作者、原文链接),商业转载请联系作者获得授权。