在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 国际许可协议 进行许可,非商业转载及引用请注明出处(作者、原文链接),商业转载请联系作者获得授权。