pytest-repeat 不适合压力测试,因其仅支持串行重复执行测试用例,缺乏并发控制、RPS调节、延迟分布统计及错误率等核心压测能力,易导致误判;它仅适用于稳定性抽检。

pytest-repeat 不能做压力测试,它只是重复执行测试用例的工具,没有并发、计时、吞吐量统计等能力。把它当压测工具用,结果既不可信,也容易掩盖真实瓶颈。
为什么 pytest-repeat 不适合压力测试
它本质是 pytest 的一个插件,只在测试生命周期内做 --count 或 --until 控制的串行重跑,每次都是完整走一遍 setup → test → teardown,不共享状态、不控制并发、不采集响应时间分布或错误率。你看到“跑了 100 次 test_login”,实际是 100 个独立、间隔明显的请求,中间还夹着 fixture 初始化和断言开销。
- 无并发:所有迭代严格串行,
--count=100≠ 100 并发连接 - 无节奏控制:无法设置每秒请求数(RPS)、阶梯加压、持续时长等关键压测参数
- 无指标输出:不提供 p95/p99 延迟、失败率、吞吐量(req/s)等核心压测指标
- 易误判:某次失败可能源于 fixture 清理不干净,而非服务承载力问题
正确做法:用专业压测工具替代
真要压测,直接换工具。Python 生态里最轻量且可脚本化的选择是 locust;如果已有 pytest 流程想复用部分逻辑,可用 pytest-asyncio + httpx 自写并发循环,但需自行补全指标采集和统计。
-
locust:支持 Web UI 实时监控、RPS 控制、用户行为建模(User Class)、分布式压测;测试逻辑写在task_set或@task中,和 pytest 完全解耦 - 自写方案示例(仅限简单场景):
import asyncio import httpx import time <p>async def single_request(): async with httpx.AsyncClient() as client: r = await client.get("<a href="https://www.php.cn/link/1c9261a8e404615b4bb8bdaee81fa0d7">https://www.php.cn/link/1c9261a8e404615b4bb8bdaee81fa0d7</a>") return r.status_code == 200</p><p>async def stress_test(n=50, concurrency=10): start = time.time() tasks = [single<em>request() for </em> in range(n)] results = await asyncio.gather(*tasks) end = time.time() print(f"Completed {n} requests in {end - start:.2f}s, success rate: {sum(results)/len(results):.2%}") </p> - 避免混用:不要在
pytest里调asyncio.run(stress_test())当压测——pytest 的事件循环管理会冲突,且 pytest 的报告机制不适用于高密度请求场景
如果你非要用 pytest-repeat,只能用于稳定性抽检
它唯一合理的用途是:验证某个测试用例在多次执行下是否稳定(比如检查资源泄漏、状态残留、随机失败)。这时你要关注的是“是否每次都通过”,而不是“花了多久”。
- 命令示例:
pytest test_api.py::test_user_create --count=50 --verbose - 关键配置:
--fail-on-collection-errors确保 setup 失败也被捕获;--tb=short避免日志爆炸 - 必须配套检查:每次运行后确认数据库/缓存/文件系统是否干净,否则
--count=50可能变成“第 49 次因脏数据失败” - 别信耗时:pytest 的
--durations=0输出的是每个 test 函数总耗时(含 fixture),不是纯接口延迟
真正做压测时,服务端日志、CPU/内存/连接数监控、慢查询记录,比 pytest 报告里的绿色点重要得多。别让工具边界模糊了问题本质。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











