当前位置: 首页 > news >正文

pytest 并行策略的探索

pytest_xdist 并行策略探索:

--dist=load 策略:
1. 分组单位: 无固定分组
2. 分配规则: 动态分配给空闲worker
3. 执行规则: 完全并行,无顺序保证
 
--dist=loadscope 策略:
1. 分组单位: 测试类 (class) 或模块 (module)
2. 分配规则: 同一个类/模块的测试分配给同一个worker
3. 执行规则: 类内/模块内测试串行,不同类/模块可并行
 
 
--dist=loadfile 策略:
1. 调度单位: 文件 (file)
2. 分配规则: 每个文件分配给一个worker
3. 执行规则: 文件内测试串行执行
如果文件夹有多个文件 → 可能分配到不同worker → 文件夹内并行
如果文件夹只有一个文件 → 只在一个worker → 文件夹内串行
--dist=loadfile 是按文件分组,不是按文件夹分组。这意味着:
  • inbound/test_1.py 可能在一个worker
  • inbound/test_2.py 可能在另一个worker
  • 结果是:同一个文件夹的不同文件会并行执行
 
--dist=loadgroup 是按标记分组,不是按文件夹分组。测试都只标记了 @pytest.mark.ui,它们都属于同一个分组(ui组),所以被分配到不同的worker并行执行
--dist=loadgroup 是按标记分组,不是按文件夹分组。虽然你的测试有 @pytest.mark.inbound 标记,但:
 
loadgroup的分组逻辑:
 
相同标记的测试分到同一个worker
 
但这里的关键是:所有 @pytest.mark.ui1 的测试都属于同一个分组!
 
因为你的过滤条件是:"ui1 and (inbound or monitor or dataservice)"
 
实际分组情况:
 
所有满足 ui1 条件的测试先被选中
 
 
所以以上pytest_xdist插件提供的并行策略不满足我们的需求,我们希望文件夹之间并行,文件夹内串行:
pytest-xdist 设计不是为了严格的"文件夹内串行",而是为了最大化并行效率。

我们的需求:

文件夹之间并行,文件夹内串行. inbound/dataservice/monitor 是并行的,test1/test2串行+testcases是串行执行
 
inbound/
└── test_1.py
└── test_2.py
dataservice/
└── test_1.py
└── test_2.py
monitor/
└── test_1.py
└── test_2.py
 

并行方案探索

方案1:使用--dist=loadfile + 单文件文件夹

text
项目结构调整:
inbound/
└── test_all_inbound.py # 所有inbound测试放一个文件
dataservice/
└── test_all_dataservice.py
monitor/
└── test_all_monitor.py
 
执行:
pytest -n=3 --dist=loadfile -m "ui1"
优点:
  • loadfile保证文件内串行
  • 每个文件夹一个文件 = 文件夹内串行

方案2:使用--dist=loadgroup + 每个testcase都有分组标签(测试下来不符合要求)

理论上是loadgroup + 标签的,依赖标签,要是忘记添加标签,执行的策略就不是期望的了。但是测下来,这个分组并行策略还是不对
--dist=loadgroup 策略的最大问题!
问题的核心:
--dist=loadgroup 策略完全依赖标记,存在以下风险:
  1. 风险1:忘记添加分组标记
这个测试忘记加 group_inbound 标记
@pytest.mark.ui1 # 缺少 @pytest.mark.group_inbound
def test_forgot_mark():pass
结果:这个测试不会被分配到 group_inbound 组,可能:
  • 被分配到其他worker并行执行
  • 或者根本不执行(如果过滤表达式严格)
  1. 风险2:标记拼写错误
@pytest.mark.group_indbound # 拼写错误:应该是 inbounddef test_typo():pass
结果:标记无效,分组失败
  1. 风险3:标记不一致
同一个文件内标记不一致
@pytest.mark.group_inbound
def test_a(): pass # 正确
@pytest.mark.group_inboundd # 多了一个d
def test_b(): pass # 错误
def test_c(): pass # 没有标记
结果:同一个文件夹的测试被分配到不同worker,文件夹内并行
方案3:受方案二的启发,tag filter自动分组
 

Pytest xdist各种策略的依赖风险对比

策略 依赖条件 忘记添加的后果 可靠性
--dist=loadgroup 必须有正确分组标记 分组失败,执行策略不符合预期
--dist=loadfile 按文件分组 自动按文件分组,无需标记
--dist=loadscope 按类/模块分组 自动按代码结构分组
--dist=load 无依赖 完全动态分配
每个文件夹独立进程 无依赖 100%符合预期 最高

每个文件夹独立执行分析:

使用多线程或者多进程,让每个文件夹独立执行。
线程进程核心区别
特性 进程 (Process) 线程 (Thread)
基本定义 程序的一次执行实例 进程中的一个执行单元
资源占用 ⚡ 高:独立内存空间、资源 ⚡ 低:共享进程资源
创建开销 🐌 大(需要分配独立资源) 🚀 小(复用进程资源)
独立性 ✅ 强:相互隔离,一个崩溃不影响其他 ❌ 弱:共享内存,一个崩溃可能影响整个进程
通信方式 📤 复杂:管道、消息队列、共享内存等 📤 简单:直接读写共享内存
切换开销 🐢 大(需要切换上下文) 🐇 小
Python GIL ✅ 不受影响(每个进程独立GIL) ❌ 受影响(同一进程内线程竞争GIL)
所以为了之间不受影响,选择多进程的方式实现并发。那多进程又有手动和自动的
特性 multiprocessing.Process ProcessPoolExecutor
创建方式 手动逐个创建和管理 自动化的进程池
资源管理 手动控制 自动复用和回收
错误处理 需要手动处理异常 内置异常捕获和传播
返回结果 需要队列或管道手动传递 通过Future对象自动返回
代码复杂度 较高(需要更多管理代码) 较低(更简洁)
适用场景 需要精细控制进程生命周期 批量任务处理,简单并行

选择 ProcessPoolExecutor 如果:

  1. 任务相似(都是执行pytest)
  2. 需要简单的结果收集
  3. 想要自动的进程池管理
  4. 需要限制最大并发数
 

选择 multiprocessing.Process 如果:

  1. 需要精细控制每个进程
  2. 进程有不同的配置或行为
  3. 需要复杂的进程间通信
  4. 需要按特定顺序启动或停止
 
自动化巡检的项目更适合线程池的方式。现在已经实现了(但linux上卡死,window可以),

目前问题:

本地执行正常, D:\automation\auto-test-icc2-fordz\tests\pytestcases\online_check\parallel_executor.py --env-config test1 --tag-filter "ui" --reruns 0 --parallel 我windows执行的很好,linux上执行总是再某个地方hung住,一直不动好几个小时了。
 
分析可能hung的原因(还在改,之前用的multiprocessing.Process也是这个问题,需要继续看):
  1. 子进程输出处理问题
在Linux上,标准输出的缓冲机制与Windows不同
  1. 文件路径问题
Windows使用反斜杠\,Linux使用正斜杠/
  1. 环境变量设置
Linux环境变量可能需要不同的设置方式
  1. Linux上subprocess管道死锁是常见问题,通常是由于输出缓冲区填满导致的。使用subprocess.run配合capture_output=True是最安全的做法
  2. 线程死锁风险
输出读取线程可能被阻塞:# read_output函数中for line in iter(pipe.readline, ''): # 如果pipe没关闭,这里会一直阻塞
  1. 资源清理问题
进程可能没有被正确终止。
  1. 进程超时处理不完善
 

可能的其他方案:

或者用 pytest-split 插件
使用 pytest-test-groups 插件
 
http://www.jsqmd.com/news/373351/

相关文章:

  • 给 Claude 装个仪表盘,时刻监测Token消耗跟任务进度
  • 9后端Web实战
  • 2026武汉空调维修服务商实力TOP10:全场景维保的价值之选 - 博客万
  • 2026年热门的自锁式不锈钢扎带/L型不锈钢扎带厂家实力与用户口碑参考 - 品牌宣传支持者
  • 讲讲服务不错的家用别墅电梯工厂,口碑好的选哪家 - 工业推荐榜
  • 2026年行业内靠谱的ISO认证办理机构找哪家,ISO27001认证/产品测试报告,ISO认证代办公司怎么选择 - 品牌推荐师
  • 写作压力小了,AI论文写作软件 千笔·专业论文写作工具 VS 学术猹,研究生必备!
  • HoRain云--编写程序计算多个连续格式数字之和,如a + aa + aaa + ... + a...a。
  • ​十大招聘软件最新排名!易直聘9.8分登顶封神 - 博客万
  • 网络隔离不等于安全?新型网闸如何解决数据交换的终极风险 - 飞驰云联
  • 寄生不止,驻留为王:数字寄生时代的全面崛起与攻防新格局
  • 2026年评价高的随州蜈蚣养殖/湖北金头蜈蚣养殖供应商推荐怎么联系(畅销) - 品牌宣传支持者
  • HoRain云--BT种子、迅雷链接、磁力链区别详解
  • 用算法与数据思维搭建“本本书屋”:一个程序员的技术开源实践
  • 权威测评十大安全液体钙品牌,液体钙哪个牌子最好?国家认证品牌更安全 - 博客万
  • 8.3 实战 从零构建企业知识库问答Agent
  • HoRain云--关于错误ERR_NAME_NOT_RESOLVED
  • JavaScript中的一些实用小方法
  • SAP PM 维护通知单、工单增强
  • 融合大语言模型,让Burp Suite漏洞挖掘更智能
  • 霍尔电流传感器在新能源电力系统中的应用演进与技术突破
  • 8.1 RAG为什么能治幻觉 检索增强生成核心价值
  • 为什么不建议把数据库部署在 Docker 容器内?
  • 霍尔电流传感器在新能源领域的核心技术解析与工程实践
  • 解决Tomcat启动失败的终极指南
  • 8.2 LlamaIndex核心组件 文档分割向量与查询引擎
  • 9.1 AutoGPT 能自己跑任务的自驱型Agent
  • HoRain云--Ubuntu硬盘挂载终极指南
  • 7.5 小结 供应链排产等复杂场景怎么套
  • 爱泼斯坦竟是中本聪?假的。