pytest默认串行执行,需在单个test函数内用ThreadPoolExecutor等实现真正并发;注意连接池配置、线程安全、变量作用域及本地环境干扰。

pytest里怎么让测试用例真正并发执行
pytest默认是串行跑用例的,pytest-xdist插件能并行,但它按test function粒度分发,不是“同一用例内多线程压测”。真要模拟高并发请求,得在单个test函数里自己控并发。
常见错误是直接用threading.Thread启动一堆线程但不等结束,导致test函数提前返回、断言失效或资源未清理。还有人误以为@pytest.mark.parametrize加ids就能压测——它只是生成多组输入,并不并发。
- 用
concurrent.futures.ThreadPoolExecutor最稳妥,配合as_completed或shutdown(wait=True) - 避免在test里用
time.sleep()模拟延迟,它会阻塞线程;改用异步HTTP client(如aiohttp)或带timeout的同步client(如requests.Session) - 每个线程必须独立维护session或连接,别共用全局
requests.Session实例——它不是线程安全的
用requests写并发请求时connection reset和timeout频发怎么办
本地预演压力测试时,ConnectionResetError或ReadTimeout不是服务端扛不住,大概率是客户端没调好。Python默认的requests底层用urllib3,连接池和超时策略不设好,线程一多就炸。
典型场景:100个线程同时发起请求,但默认只开10个连接,其余全在排队,超时后报错。
- 给
requests.Session配连接池:adapter = requests.adapters.HTTPAdapter(pool_connections=100, pool_maxsize=100),再session.mount("http://", adapter) - 显式设
timeout=(3, 7)(connect + read),别留空或只设一个值 - 禁用DNS缓存(尤其本地host映射):
session.headers.update({"Connection": "close"}),或用urllib3.util.connection.create_connection绕过系统DNS
pytest参数化+并发组合使用时数据隔离怎么做
想用@pytest.mark.parametrize传不同URL或payload,再在每个参数分支里起20个线程压测?小心变量作用域和闭包陷阱。lambda里引用循环变量i,最后所有线程都拿到同一个值,是高频翻车点。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
更麻烦的是fixture复用:比如用@pytest.fixture(scope="function")初始化一个DB连接,但并发线程共享它,写操作会冲突或报sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in that same thread。
- 参数化数据直接传进test函数参数,别在for循环里定义线程target函数
- 线程内需要资源(如DB连接、临时文件)必须在线程内部创建,别从外层传入可变对象
- 用
threading.local()做线程局部存储,比如local_data = threading.local(),然后各线程存自己的local_data.session
本地预演结果不准,和线上压测差距大的关键原因
本地用pytest+多线程跑出QPS 500,上线后用wrk或locust一测才200,不是代码问题,是环境干扰太强。Python GIL、本机网络栈、防火墙、甚至Wi-Fi信号都会吃掉真实吞吐。
最容易被忽略的是:你压的是localhost,TCP走loopback,没经过网卡和iptables,而线上请求要过负载均衡、WAF、服务网格……链路长得多。
- 本地预演只验证逻辑通路和临界值(比如并发到多少开始503),不追求绝对QPS数字
- 关掉杀毒软件、Chrome和其他占用网络的进程;Linux下用
netstat -s | grep -i "retransmit"看重传率,高于2%说明网络层已瓶颈 - 用
psutil.net_io_counters()在压测前后抓本机收发字节数,如果远小于请求体总大小,说明大量请求根本没发出去——十有八九是连接池或文件描述符耗尽
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










