自动化测试框架如何管理测试设备

接入与开发

讲清自动化测试框架里设备池怎么分层、怎么加锁排队、怎么处理掉线和并发不均,给出一套能直接照着改的调度方案。

做移动端或跨端测试的团队,脚本本地跑得挺好,一接进 CI 就出问题:任务抢同一台机器、设备中途掉线没人回收、并发一开高就大面积失败。这篇不讲协议也不讲客户端配置,只讲工程侧怎么把设备池管起来——设备怎么注册与打标、任务怎么排队和加锁、超时和掉线怎么兜底、并发数怎么定,最后给一份上线前的检查清单。

脚本在本地跑得好好的,一接进 CI 就开始出怪问题:两条流水线抢同一台机器、设备跑一半掉线没人管、并发从两开上去直接大面积失败。这类问题多半不是脚本写错了,而是设备池没管起来。设备在框架里应该是一份有状态、有租约、能被回收的资源,而不是写在配置文件里的一串 UDID。

这篇只讲工程侧怎么把设备池管住:设备怎么登记打标、任务怎么排队加锁、掉线和超时怎么兜底、并发数怎么定,最后给一份上线前的检查清单。协议层和客户端配置不在范围内,那些在站内工具目录和指南中心另有页面讲。设备型号与系统覆盖率的现状数字,到 /tools/model-db 核对当时的数字。

第一步:设备怎么登记、怎么打标

登记的第一原则是:设备信息要落成结构化数据,由调度层读写,脚本里只声明需求,不出现具体机器标识。硬编码 UDID 的写法在设备换一台、坏一台之后就要改代码,团队越大越难维护。每条设备记录至少要能回答:它是谁、能跑什么、现在被谁占着、多久没联系了。

字段类别该写什么为什么必须有
唯一标识设备自身标识 + 池内别名调度和日志都要能对上同一台机器
适配能力平台、系统大版本、机型档位、特殊硬件能力按标签选设备,脚本不写死机器
运行状态空闲 / 占用 / 排障中 / 停用状态取值不明确就会出现幽灵占用
占用信息当前任务、占用开始时间、租约到期时间没有这块就无法判断锁是否该回收
心跳时间设备侧与驱动侧各自最近一次响应时间掉线检测要靠它,缺了只能靠猜
  • 把设备清单做成可导出、可对账的接口,而不是散落在各台执行机的本地配置里;
  • 给设备打标签比给设备起名字重要:机型档位、系统大版本、是否支持网络降级这类能力,都是调度依据;
  • 区分常驻池和弹性池:真机一般常驻且独占,模拟器和云设备可以按需拉起,两类设备别共用一套状态机;
  • 状态字段的取值和迁移规则要写进文档,谁在什么条件下能把设备从占用改回空闲,必须只有一个入口。

第二步:任务怎么排队、设备怎么加锁

加锁之前先定粒度:一个测试类占一台设备,还是一个用例占一台设备。粒度太细,申请释放的开销会吃掉并发收益;粒度太粗,一条长用例会把整条队列堵住。多数移动端回归选中间档——按用例组或测试文件占设备,跑完整个文件再释放。

锁本身要带租约,不能只靠申请和释放两个动作。拿到设备的进程要定期续约,续约失败就自动回收。只做两步锁的话,进程被 kill 或者容器被重建之后,设备会永久卡在占用状态,只能靠人工去改数据库。

  1. 申请任务提交时只声明标签需求(平台、系统大版本、需要的硬件能力),由调度层去匹配空闲设备;不要指定具体机器。
  2. 加锁与续约匹配成功后写入占用者和租约到期时间,执行进程按固定间隔续约;验证方式是手动 kill 一次执行进程,看设备是否在租约到期后回到空闲。
  3. 排队与优先级紧急回归可以插队,但每类任务都要有等待上限;超过上限直接明确失败,不要让任务无限等下去把整条流水线挂住。
  4. 释放与并发上限释放走统一出口,同时校验占用者身份,防止过期进程误释放。并发上限按可用设备数设,并留出至少一到两台冗余设备给排障和临时验证。

第三步:超时、掉线与回收怎么兜底

超时要分三层设:单条用例超时、单台设备的会话超时、整个任务的总超时。只设最外层超时,失败日志里只能看到任务超时,根本分不清是脚本卡住了还是设备没响应,排查成本会翻好几倍。三层里最内层的数值要明显小于外层,给回收动作留出时间。

掉线检测建议用两个信号:设备侧心跳、驱动侧会话是否还能响应。只有心跳失联,可能只是采集通道的问题,重启会话往往就够;只有会话失联但心跳还在,通常是应用或驱动层卡死,需要重置会话并清理应用数据;两个都失联,才按整机重置处理。

  • 回收动作必须幂等:重置会话、清应用数据、必要时重启设备,重复执行不应产生副作用;
  • 回收失败的设备打上标记,进人工排障队列,绝对不能默默塞回空闲池;
  • 每次失败记录设备标识、失败阶段、回收结果三样信息,缺一样后期都没法归因;
  • 连续多台设备在同一个阶段失败,先怀疑环境而不是脚本,比如网络出口或设备固件批次。

第四步:并发数怎么定,别靠感觉

并发数要从基线推出来,不是拍脑袋定的。先在同一批用例上跑单台设备的完整一轮,拿到稳定耗时和失败率,基线不稳的时候加并发只会放大噪声。基线稳定之后再逐步往上加,每加一档观察一轮,看失败率有没有跳变。

观察指标偏高说明什么偏低说明什么
设备利用率池子里有不少设备在空转,可以缩容或提高并发
排队等待时长设备不够用,任务在等机器;若等待时长超过执行时长就该扩池
失败率随并发变化并发一提高失败率就跳,多半是环境或资源竞争问题,不是脚本问题
单台执行耗时耗时明显拉长,说明设备侧有资源争抢,比如共享网络或存储

稳定并发和峰值并发要分开看。日常回归按稳定并发跑,发版前的高峰用排队扛,而不是临时扩一批没预热的设备进来——冷设备首次执行的成功率通常明显低于常驻设备,实测数字可以到 /tools/speed-test 对照当时的记录。真机和模拟器的并发要分开算,两者启动成本和失败模式差很多,用同一个数字往往一边饿死一边过载。

上线前的检查清单

这套东西改完之后,别急着把并发拉满。先按下面几条逐项过一遍,确认没有明显漏洞再逐步放量。清单本身也可以当做排障顺序用:线上出问题的时候从上往下查,通常能在前几条里定位到原因。

  • 设备清单可导出可对账,确认没有长期不出现在任何执行记录里的僵尸条目;
  • 排查是否存在没有租约的锁、只申请不释放的分支,以及异常路径下锁能不能被回收;
  • 三层超时是否都配了值,失败日志里能否一眼看出是哪一层超时;
  • 并发数是否基于实测基线,峰值场景是否有排队上限而不是无限堆积;
  • 排障队列有没有人看,连续失败的设备会不会被自动重新投进池子;
  • 设备标签与脚本声明的需求是否对得上,有没有脚本仍在写具体机器标识。
设备池的核心不是并发数调得多高,而是每一台设备在任意时刻都有明确的归属和回收路径。
下一步把设备清单和超时配置对照站内指南过一遍,再看一眼模型与工具侧的现状记录,确认你的设备标签覆盖了常用的机型档位。

常见问题

设备池用现成平台还是自己写调度?

看规模和变动频率。设备数量稳定、团队只有一两条流水线,用现成的云测平台或开源调度通常更省事;设备种类杂、需要按标签精细选机、还要和内部发布流程绑定,自己写一层调度更可控。判断标准是:你需要的调度规则现成方案能不能配出来,配不出来的部分就是自研的理由。

并发一开高就大面积失败,先查哪里?

先确认失败是集中在少数几台设备还是均匀分布。集中的话优先查那几台机器的状态和回收逻辑;均匀分布则多半是并发超过了环境承载,常见原因是共享资源争抢(同账号、同测试数据、同后端环境),这时降并发或做数据隔离比改脚本更有效。

设备中途掉线,任务该判失败还是重试?

先区分掉线阶段。用例还没开始执行就掉线,直接换设备重试代价很低;执行到一半掉线,重试要连带清理数据,否则可能留下脏状态。通用做法是设定一个重试上限,并且把掉线重试和断言失败分开计数,避免把真正的缺陷当成环境抖动重试掉。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。