移动端自动化:多设备并发测试怎么管理才不会把真机环境跑崩
移动端自动化一旦从“单机单设备”走向“多设备并发”,会很快碰到一个现实问题:
不是用例不会跑,而是真机环境越来越不稳定。
最典型的表现通常是这些:
- 同一条命令偶尔跑到别的设备上
- 设备昨天还能用,今天跑两轮就开始
offline - 截图、日志、录屏和实际失败设备对不上
- 某个 case 跑挂以后,把后面的设备状态一起污染了
- 并发一上来,整套环境吞吐没上去,故障反而更多
这类问题本质上已经不是“单条 ADB 命令怎么写”,而是设备管理问题。
如果设备管理没有体系,再好的自动化脚本、再全的日志采集、再多的设备数量,最后都会被环境不稳定抵消掉。
所以这一篇我想讲的是:
多设备并发测试到底怎么管理,才能让真机环境真的可用,而不是看起来设备很多,实际没人敢开并发。
一、多设备并发最容易被低估的问题,不是并发本身,而是“资源争抢”
第一次做移动端并发时,重点很容易先放在“能不能同时起 10 个任务”。
但真实项目里,最先出问题的往往不是线程数,而是资源边界没定义清楚。
在真机环境里,至少有四类资源会被争抢:
- 设备本身
- ADB 连接
- 执行机资源
- 证据产物目录
只要这几类资源里有一类没隔离好,并发执行就会开始出现诡异问题。
比如:
- 两个任务误用同一台设备
- 一个任务重启了 ADB,影响所有设备
- 截图都写到同一个目录里,最后文件串了
- 同时拉日志、录屏、截图,把执行机 I/O 打满
所以多设备并发的第一原则不是“把任务并起来”,而是:
先把资源边界和占用关系定义清楚。
二、设备调度的第一件事,不是分配设备,而是先定义设备状态机
做设备调度时,只维护一个“可用设备列表”。这在设备很少时还能勉强工作,但规模一大就会失控。
更推荐的做法是:先把设备状态定义清楚,再做调度。
最起码,会把设备分成下面几种状态:
idle:空闲,可分配busy:已被任务占用recovering:正在执行恢复动作quarantine:疑似异常,暂时摘除offline:连接不可用maintenance:人工维护中
这个状态机的价值非常直接。
1. 防止设备重复分配
如果没有 busy 状态,很容易出现两个任务几乎同时拿到同一台设备。
2. 防止坏设备继续流入调度
如果设备刚刚发生:
- 连续安装失败
- 截图失败
- 录屏异常
- 多次
offline
那它就不应该立即回到可用池,而应该先进入 quarantine 或 recovering。
3. 让调度层和恢复层职责分开
调度层只关心“能不能分配”;恢复层只关心“这台设备能不能被救回来”。
这两个逻辑如果混在一起,系统会越来越难排查。
三、设备占用更适合做成“显式租约”,不能只靠内存变量
这件事非常重要。
一开始做并发执行,会在代码里维护一个“当前已占用设备集合”,看起来很简单,但实际很脆弱。
因为只要发生下面这些情况,就会出错:
- 任务进程崩了
- 执行机重启了
- 调度服务和执行服务不在同一进程
- 多个 worker 同时抢设备
所以更推荐把设备占用做成显式租约,至少包含这些信息:
- 设备序列号
- 任务 ID
- 占用开始时间
- 心跳更新时间
- 占用过期时间
这样做的好处是:
- 设备归属关系清晰
- 任务异常退出后可以自动回收
- 更容易排查“这台设备现在到底被谁占着”
否则一旦环境变复杂,最常见的现象就是“设备明明空着,却没人敢动”,或者“设备看起来空闲,实际背后还有残留任务没清掉”。
四、所有设备命令都必须强制绑定序列号,这是并发环境的底线
这个问题看起来基础,但在多设备环境里是最高频的事故源之一。
只要环境里同时连着两台及以上设备,所有命令都必须强制带:
1 | adb -s <serial> ... |
这件事不能靠口头提醒,必须在封装层强制。
因为只要漏掉一次,就可能出现:
- 命令发到默认设备
- 日志采到别的设备
- 截图和录屏归档错误
- 清数据动作误伤另一台设备
单设备环境里这类问题不明显,一上并发就会放大成严重事故。
所以更稳妥的建议一直是:
- 底层命令封装层强制要求传
serial - 没传序列号直接拒绝执行
- 报告和日志里所有证据都显式带设备标识
五、并发环境最怕的不是设备少,而是设备脏
一开始会把精力放在“再多买几台手机”,但如果设备生命周期管理没做好,设备越多,脏设备也越多,环境维护成本只会跟着上升。
所谓设备脏,通常包括几类情况:
- 应用残留进程没清掉
- 上一轮测试账号没退出
- 权限弹窗残留
- 录屏和日志文件残留
- 屏幕停在异常页面
- 网络状态被前一轮测试改掉
这类问题最麻烦的地方在于,它们不一定每次都导致失败,但会让失败变得越来越随机。
所以每次任务结束后,设备都应该有一套明确的收尾动作,而不是“任务跑完就算结束”。
六、更推荐的设备生命周期:分配前检查、执行中守护、结束后回收
如果想把真机环境跑稳,更倾向把一台设备的执行生命周期拆成三段。
1. 分配前检查
目标是确认这台设备值得被分配。
通常会检查:
- 是否在线
- 是否
device状态 - 电量是否过低
- 存储空间是否不足
- 是否存在异常残留文件
- 是否有目标应用残留进程
如果这些基础检查都不过,不应该把设备直接投入执行。
2. 执行中守护
目标是避免任务跑到一半时,设备 silently 崩掉。
通常会关注:
- 设备是否 still online
- 日志采集是否还在
- 录屏是否成功启动
- 应用进程是否还存在
- 关键命令是否持续超时
的任务失败后才去看设备状态,这太晚了。
真正稳的系统会在执行中持续感知设备健康。
3. 结束后回收
目标是让设备尽量回到标准初始态。
常见动作包括:
- 停止目标应用
- 清理临时文件
- 拉回证据产物
- 删除设备侧录屏
- 回到桌面
- 必要时清应用数据
如果任务结束后没有统一回收,脏状态会不断积累,最终把整个设备池拖垮。
七、设备恢复更适合分层,不能遇到失败就直接重启
在真机环境不稳定时,最常见的补救方式就是“重启手机”。
这个动作不是不能用,但如果把它当成默认恢复手段,成本非常高。
更倾向把恢复分成三层。
1. 轻恢复
适用场景:
- 页面卡住
- 应用停在异常页
- 截图或输入短暂异常
常见动作:
- 回桌面
- 强杀目标应用
- 清理临时文件
- 重新拉起应用
2. 中恢复
适用场景:
- 应用数据明显脏掉
- 多次启动失败
- 日志和录屏能力异常
常见动作:
- 清应用数据
- 重建 ADB 会话
- 重跑基础健康检查
3. 重恢复
适用场景:
- 设备频繁
offline - 系统卡死
- 存储异常
- 连续多轮恢复失败
常见动作:
- 重启设备
- 从调度池摘除
- 标记人工检查
分层的意义在于:不是每个失败都值得付出最高恢复成本。
如果恢复策略过重,并发吞吐会被拖垮;如果恢复策略过轻,脏状态又会继续传播到后续任务。
八、并发执行时,证据也要按设备和任务双重隔离
多设备并发很容易被理解成只要“命令不要串”就够了,但实际另一个高频事故点是证据产物串了。
典型现象包括:
- A 设备的截图挂到了 B 设备的报告里
- 一个 case 的日志被另一个任务覆盖
- 录屏文件名重复,后写覆盖前写
所以多设备环境下,证据目录必须至少按下面两个维度隔离:
- 设备序列号
- 任务或 case 标识
例如:
1 | outputs/ |
这样哪怕同一个 case 同时在两台设备上跑,证据也不会串在一起。
九、执行机资源也要被当成并发约束,不然设备多也没用
做真机并发时,只看设备数量,不看执行机瓶颈。这会导致一个错觉:设备明明足够多,但整体执行速度就是上不去。
常见瓶颈包括:
adb子进程太多- 日志采集太多导致 CPU 占用上升
- 截图、录屏、文件拉取导致 I/O 饱和
- 大量并发分析日志导致执行机变慢
所以并发上限不能只按设备数来设,还要结合:
- 执行机 CPU
- 内存
- 磁盘 I/O
- USB Hub 或网络调试链路稳定性
否则你会看到一种很典型的现象:设备数量翻倍了,但故障率也翻倍,实际吞吐反而下降。
十、在项目里踩过的几个真机并发坑
坑 1:设备池里“看起来可用”的设备,其实已经半坏了
现象:
adb devices能看到- 偶尔也能执行命令
- 但安装、截图、录屏成功率明显偏低
如果调度层只看“在线/离线”,这种设备会不断被重新分配,最终制造大量偶发失败。
修复思路:
- 增加健康分或失败计数
- 连续异常达到阈值后自动摘除
- 不让“勉强能用”的设备继续参与调度
坑 2:任务异常退出后,设备一直处于假占用状态
现象:
- 设备没人真正使用
- 但调度系统一直认为它被占着
根因通常是没有租约超时和心跳回收。
修复思路:
- 占用记录加 TTL
- worker 定期续约
- 超时未续约则自动释放并进入健康检查
坑 3:恢复动作误伤了别的任务
现象:
- 某个任务失败后执行了
adb kill-server - 结果所有设备一起受影响
这类问题说明恢复动作粒度太粗。
在并发环境里,任何全局性动作都要极度谨慎,因为它可能不是“修一台设备”,而是“把整个执行面一起打断”。
坑 4:问题明明出在环境,却被误判成业务缺陷
这种情况非常常见。
比如:
- 某台设备存储空间满了
- 权限弹窗残留
- 录屏文件没删
- 某个 USB 口不稳定
最后表现出来可能只是“登录失败”或“元素不存在”,如果没有设备健康上下文,很容易被当成业务问题。
十一、更推荐的一套真机并发管理思路
如果后面要做成平台或稳定的 CI 资产,更推荐至少把能力拆成下面几层。
1. 设备注册与发现层
职责:
- 发现设备
- 同步设备元信息
- 感知在线状态
2. 调度与租约层
职责:
- 分配设备
- 维护占用关系
- 处理续约和超时释放
3. 健康检查与恢复层
职责:
- 执行分配前检查
- 执行中监测
- 失败后恢复
- 坏设备摘除
4. 任务执行与证据层
职责:
- 跑用例
- 采集日志、截图、录屏
- 按设备隔离证据
把这几层拆开以后,环境才会逐渐稳定。
如果全都堆在一个执行脚本里,问题一多就很难继续演进。
十二、排查真机并发问题时,可以按什么顺序看
当并发环境出问题时,更稳的做法通常不是先去看业务日志,而是按下面顺序排查。
1. 先看是不是设备分配错了
确认:
- 是否重复分配
- 是否租约没释放
- 是否命令带了正确序列号
2. 再看设备自身是不是健康
确认:
- 是否频繁
offline - 是否空间不足
- 是否存在异常残留文件
- 是否处于恢复中却被重新分配
3. 再看执行机是否被打满
确认:
- CPU 是否过高
- I/O 是否拥塞
adb进程数是否异常
4. 最后再看业务失败本身
因为很多“业务失败”,前面三步就已经能定位出是环境问题。
如果上来先看用例断言,经常会把环境问题误判成产品缺陷。
结语
多设备并发测试真正难的,从来不是“怎么把线程开起来”,而是怎么让设备、任务、证据和恢复动作在并发环境下仍然保持有序。
更关键的是一套真正可用的真机并发管理,至少要做到:
- 设备状态清晰,不是只有在线和离线
- 占用关系可追踪,不靠进程内变量硬记
- 设备命令强制绑定序列号
- 分配前检查、执行中守护、结束后回收形成闭环
- 故障设备能被自动摘除,而不是反复污染环境
- 证据和资源都能按设备隔离
如果这些基础能力没补齐,设备越多,并发越高,环境只会越乱;
只有把调度、隔离、恢复和排障一起做起来,真机环境才会从“能跑”变成“敢长期跑”。