pytest 7.0+原生支持async def测试函数,无需插件;但需满足版本≥7.0、函数名以test_开头、不可在普通def中await,否则报“coroutine was never awaited”;async fixture等复杂场景仍需pytest-asyncio。

pytest 7.0+ 原生支持 async def 测试函数,无需插件
Python 3.11 + pytest 7.0 及以上版本已内置对 async def 测试函数的支持——只要 pytest 版本够新,直接写 async def test_something() 就能跑,不用装 pytest-asyncio 或手动 loop.run_until_complete()。
但要注意:pytest 默认不 await 测试函数,它依赖内部的异步执行器(由 pytest 自动识别并调度),所以必须满足两个条件:
- 测试函数必须是
async def,不能是普通函数里调await - pytest 必须 ≥ 7.0(推荐 ≥ 7.2,修复了早期 async fixture 的竞态问题)
- Python 解释器需为 3.7+(3.11 当然完全兼容)
遇到 RuntimeWarning: coroutine 'test_xxx' was never awaited 怎么办
这是最常见报错,本质是 pytest 没识别出你的测试是异步的——通常因为版本太低或命名/结构不合规。
检查以下几点:
- 运行
pytest --version,确认输出包含pytest 7.x;若显示 6.x,升级:pip install -U pytest - 测试函数名必须以
test_开头,且不能嵌套在类方法里(除非该类继承unittest.IsolatedAsyncioTestCase,但这就不是纯 pytest 路线了) - 不要在
def test_foo():里写await some_async_func()——这会触发 warning,因为普通函数不会被 await - 避免在测试中混用
asyncio.run():它会新建事件循环,可能和 pytest 内部循环冲突
正确示例:
import pytest
async def test_fetch_data():
result = await my_async_api_call()
assert result == "ok"
pytest-asyncio 还需要吗?什么时候必须用
绝大多数纯函数级异步测试不需要 pytest-asyncio。但它在两类场景仍是刚需:
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
- 需要自定义事件循环策略(如 uvloop)或控制 loop 生命周期(例如复用同一个 loop 多次测试)
- 要写
async deffixture(比如@pytest.fixture返回 awaitable),而 pytest 原生只支持同步 fixture;此时必须加@pytest_asyncio.fixture装饰器,并安装pytest-asyncio - 测试涉及多个协程并发(
asyncio.gather)、超时控制(asyncio.wait_for)等复杂调度逻辑,用插件更可控
注意:启用 pytest-asyncio 后,需在 pytest.ini 或 pyproject.toml 中声明策略,否则可能静默失败:
[tool:pytest] asyncio_mode = "auto"
测试异步 fixture 和依赖注入容易卡在哪
原生 pytest 不支持 async def fixture,所以如果你写了:
@pytest.fixture
async def db_conn():
conn = await connect_db()
yield conn
await conn.close()
pytest 会把它当同步 fixture 处理,await 不执行,conn 是个 coroutine 对象,后续 await db_conn 会报 TypeError: object XXX can't be used in 'await' expression。
解决路径只有两条:
- 用
pytest-asyncio+@pytest_asyncio.fixture(推荐,语义清晰) - 退回到同步 fixture,在里面用
asyncio.get_event_loop().run_until_complete(...)——但仅限简单 case,且 Python 3.11 中get_event_loop()在非主线程可能抛RuntimeError
另一个坑:异步 fixture 之间不能循环依赖,pytest 不检查 async fixture 的依赖图,错误会在运行时才暴露,调试成本高。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










