pytest不支持异步压力测试,需用locust等专业工具;它仅适合压测前后的状态校验,如服务健康检查、db/缓存指标验证。

pytest本身不支持异步压力测试,得换工具
pytest 是单元测试框架,不是压测工具;它连 async def 测试函数都需靠 pytest-asyncio 插件才能跑通,更别说并发发压。直接用 pytest + asyncio.gather 模拟多请求,顶多算「并发调用验证」,无法控制 RPS、阶梯加压、统计吞吐/延迟分布——这些是压测的核心诉求。
真正可行的路径是:用 FastAPI 启一个本地服务(uvicorn.run(..., host="127.0.0.1", port=8000)),再用专业压测工具打它。pytest 在这里只适合做「前置准备 + 后置断言」,比如启动服务、清理临时 DB、校验压测后状态是否符合预期。
用 locust 做 FastAPI 异步压测最省事
Locust 原生支持 async HTTP 客户端(HttpUser 默认用 httpx.AsyncClient),和 FastAPI 的 async 生态天然对齐。不用改接口代码,也不用写同步 wrapper。
- 安装:
pip install locust httpx - 写
locustfile.py,用async def写任务,直接 awaitself.client.get("/items") - 启动:
locust -f locustfile.py --host http://127.0.0.1:8000 - 打开
http://localhost:8089配置用户数和 spawn rate
注意:FastAPI 服务必须已运行(别在 locustfile 里用 uvicorn.run 阻塞主线程),且路由要带完整路径(如 /items 而非 http://127.0.0.1:8000/items,因为 --host 已指定 base URL)。
pytest 可以配合做压测前后的状态检查
比如你想验证高并发下数据库连接没泄漏,或缓存命中率达标——这些没法在 locust 报告里直接看,就得让 pytest 接管「压测前后」的探针逻辑。
- 用
subprocess.Popen启动 uvicorn(后台)、locust(命令行模式)、再杀掉它们 - 压测前:pytest 调用
httpx.AsyncClient请求/health确认服务就绪 - 压测后:pytest 查询 DB 表行数、Redis
INFO memory、或读取 locust 生成的stats_history.csv - 关键点:所有异步操作必须显式
await,pytest 默认不支持 async fixture,得加@pytest.mark.asyncio和pytest-asyncio
示例片段:
@pytest.mark.asyncio
async def test_after_load_cache_hit_rate():
async with httpx.AsyncClient() as client:
r = await client.get("http://127.0.0.1:8000/metrics")
assert "cache_hits_total" in r.text
assert float(r.text.split("cache_hits_total ")[-1].split("\n")[0]) > 1000
别在 FastAPI 路由里加 print 或 time.sleep
压测时任何阻塞操作都会扭曲结果。常见坑:
-
print()在高并发下会锁 stdout,导致请求卡住——改用logging.info()并配置异步 handler -
time.sleep(1)是同步阻塞,直接让整个 event loop 停摆;必须换成await asyncio.sleep(1) - DB 查询没加
async驱动(比如用sqlite3而非aiosqlite),会把线程池拖满 - Pydantic v2 的
model_dump()比 v1 的dict()快很多,大响应体场景建议升级
真实瓶颈往往不在 FastAPI 本身,而在你写的 async 函数里混了同步调用,或者没配好数据库连接池大小(pool_size 和 max_overflow)。压测前先用 asyncpg 或 aiomysql 替掉 psycopg2 这类同步驱动。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











