Skip to content

Monkey 扰动

入口页只负责入口;随机扰动能力的参数、运行方式和返回结构继续看这里。 重点是看什么时候该用扰动、参数怎么调,以及哪些结果字段能直接拿来验收和排错。

先判断是不是这页的范围

  • 你要做随机事件扰动、稳定性压测、异常发现:看这里
  • 你要调随机种子、事件节奏、触摸/滑动/导航占比、总事件量:看这里
  • 你要做稳定页面点击、输入和等待,不要先从 Monkey 文档开始
  • 你只是想知道设备与 UI 执行的整体分层,先去设备与 UI 实战

怎么读这页

  • 先看“能力边界和操作方式”,确认它更适合会话式运行,而不是一步到位的短动作
  • 再看参数说明,理解默认值适合什么场景、该往哪个方向调
  • 最后看底层命令和结果字段,确认怎么留证、怎么复现、怎么排错

这页解决什么问题

  • 这组扰动能力到底做了什么
  • 启动阶段需要哪些参数
  • 默认值适合什么场景
  • 返回结果里哪些字段可以直接拿来验收或排错

一句话理解:

  • Monkey 负责扰动和异常暴露
  • 它不是稳定执行路径的替代品

能力边界和操作方式

当前对外暴露的是一组会话式扰动操作

  • monkey_start:提交一次后台随机扰动,并立即返回会话信息
  • monkey_status:查询当前是否仍在运行;没有活跃会话时返回最近一次结果或 idle
  • monkey_wait:在需要最终结果时显式等待当前扰动结束;没有活跃会话时返回最近一次结果或 idle
  • monkey_stop:主动收束当前运行中的扰动;没有活跃会话时返回最近一次结果或 idle
  • monkey_clear:删除最近一次缓存的摘要结果;若当前仍有活跃会话,会提示先停止

默认推荐流程:

  • 先调用 monkey_start
  • 启动后优先调用 monkey_status 看进度
  • 只有用户明确要求“等它跑完并给最终结果”时,才调用 monkey_wait
  • 如果用户只想先跑起来,不要在 monkey_start 后立刻跟 monkey_wait

当前实现默认由 adb monkey 自己拉起目标应用;如果你想从某个稳定页面起跑,应在调用 monkey_start 前自行把应用带到前台。 前台守护默认只记录失焦,不会自动 stop/restart 当前 monkey。

对使用者来说,只需要记住它负责“对目标应用注入随机事件,并持续暴露过程状态与异常摘要”这一件事,不必依赖内部目录结构。

启动前要想清楚什么

如果你只是“先跑起来看看”,其实只需要想清楚下面这些问题:

  • 要测哪一个应用
  • 是想固定随机序列做复现,还是想多探索一些路径
  • 扰动节奏要偏快还是偏慢
  • 更偏重点击,还是想要更多滑动、滚动、导航切换
  • 这轮是快速冒烟,还是长时间稳定性压测
  • 是否需要观察应用有没有跳出前台
  • 一旦跳出前台,是只记录、直接停止,还是判为失败
  • 会话结束后要不要顺手落盘完整日志
  • 多设备场景下,不同设备是否要用不同配置

状态查询、等待、停止和清理属于会话管理动作,本身不需要你再重复描述这些启动意图。

怎么描述你的启动意图

目标应用

这是最基本的输入。

作用:

  • Monkey 只会针对这个应用注入随机事件

建议:

  • 跑前先确认应用已经安装
  • 更稳的链路里,通常先把应用手动带到前台,再开始扰动

随机序列

默认会使用一组固定随机序列,方便复现。

作用:

  • 控制这一轮事件分布的大致随机走向
  • 相同环境下更容易复现同类问题

建议:

  • 做回归时尽量固定
  • 做探索时可以换一组随机序列扩大覆盖

扰动节奏

默认节奏偏中等,不是极快压测,也不是接近人工慢速操作。

影响:

  • 节奏越快,压力越大
  • 节奏越慢,页面有更多时间完成切换和加载

建议:

  • 想看高压稳定性就加快
  • 想减少误触发和切页抖动就放慢

事件偏好

默认更偏点击,辅以一定比例的滑动和导航类动作。

作用:

  • 决定这一轮更像“重点击乱点”,还是“带滚动和切换的探索”

建议:

  • 交互密集的页面可以维持较高点击占比
  • 列表页、长页面、画廊页可以增加滑动类动作
  • 如果只想在当前页面内部做扰动,可以减少导航类动作

事件总量

默认事件量偏大,更适合中长时运行。

影响:

  • 事件量越大,测试越久
  • 覆盖更广,但也更容易引入长尾问题

建议:

  • 快速冒烟先从小事件量开始
  • 稳定性压测再逐步拉长

起跑入口

当前实现默认由 adb monkey 自己拉起目标应用。

作用:

  • 决定这一轮从哪里开始进入应用

建议:

  • 如果你希望从某个稳定页面起跑,应在启动前自行把应用带到那个页面
  • 文档里提到的入口信息更像辅助标识,不会替代你手动准备起跑现场

前台守护

默认会观察目标应用是否还在前台,但不会自动接管会话。

作用:

  • 帮你知道这一轮是否已经跑偏到别的应用、桌面或系统界面

建议:

  • 你关心“这轮是否还在目标应用内”时保持开启
  • 你明确接受跳出目标应用继续跑时再关闭

守护敏感度

守护本身有几个可调维度,但你不需要记内部字段名,只要记住这三个意思:

  • 检查有多频繁
  • 启动初期要不要给应用一段宽限时间
  • 要连续偏离几次才算真正跑偏

建议:

  • 系统弹窗、通知栏、转场动画较多时,把守护调得宽松一点
  • 想更快发现跑偏,就让检查更频繁、阈值更低

跑偏后的处理方式

当前只支持三种自然语义:

  • 只记录:记下已经跳出前台,但不自动打断这轮 monkey
  • 直接停止:发现跑偏后就收束当前会话
  • 记为失败:发现跑偏后把这轮直接判失败

建议:

  • 默认先用“只记录”
  • 你只关心“不能跑出目标应用”时再用“直接停止”
  • 你把“离开前台”本身视为缺陷时再用“记为失败”

日志留存

可以让 monkey 结束后把这一轮 logcat 自动落盘。

适合:

  • 你需要留下 crash / ANR / OOM 的完整证据
  • 你已经有现成的报告目录,希望顺手把日志汇总进去

注意:

  • 当前实现会在给定目录下创建独立子目录,避免并发覆盖

多设备差异化

多设备场景下,可以让不同设备带不同启动意图。

适合:

  • 不同设备跑不同应用
  • 同一轮里,不同设备使用不同事件量、不同节奏或不同随机序列

底层实际命令

当前实现会拼出类似这样的命令:

adb -s <serial> shell monkey -p <package> \
  -s <seed> \
  --throttle <throttle_ms> \
  --pct-touch <touch> \
  --pct-motion <motion> \
  --pct-nav <nav> \
  --pct-appswitch 0 \
  --pct-syskeys 0 \
  --ignore-crashes \
  --ignore-timeouts \
  --ignore-security-exceptions \
  -v -v <events>

这里有几个重要点:

  • --pct-appswitch 0
  • 不主动做应用切换
  • --pct-syskeys 0
  • 不主动打系统键
  • --ignore-crashes
  • --ignore-timeouts
  • --ignore-security-exceptions
  • 这些参数保证 Monkey 尽量继续跑,而不是一遇到异常就立即停

所以当前这套更偏:

  • 在目标包内做稳定性扰动
  • 不把系统级跳转比例开太大

实际执行流程

底层流程不是单纯启动一条命令。

当前实现顺序更接近:

  1. 清空日志缓存
  2. 建立日志跟随
  3. 等待约 0.2s
  4. 启动一段 monkey segment
  5. 可选启动前台守护轮询
  6. 并行读取运行输出与日志输出
  7. 按关键词沉淀摘要、统计和证据片段
  8. 守护只负责观察或收束当前会话;默认 observe 只记录,不接管生命周期
  9. 全部事件完成或会话被停止后,回收运行进程与日志跟随

如果按会话方式使用,启动动作会先返回;后续再通过状态查询、等待或停止去管理这次运行。 如果启动时传了 saved,当前实现会在结束后把本轮 logcat 导出到该根目录下的独立子目录,便于回放 crash / ANR 证据。

内置关键词监测

当前会监测这几类异常:

  • crash
  • anr
  • oom
  • monkey_abort

内置匹配关键词包括但不限于:

  • FATAL EXCEPTION
  • AndroidRuntime
  • Fatal signal
  • SIGSEGV
  • SIGABRT
  • ANR in
  • Application Not Responding
  • Input dispatching timed out
  • OutOfMemoryError
  • Failed to allocate
  • Monkey aborted
  • Monkey finished
  • Events injected:

注意:

  • 只有命中这些关键词的行,才会进入 tail
  • 这能降低噪音,但不等于完整 logcat 全量存档

返回结构

返回里最重要的是 data 字段。当前更适合重点关注:

  • 这一轮当前是在运行、已结束、已停止还是已失败
  • 当前大约跑了多少事件,还剩多少
  • 这轮对应的是哪台设备、哪个目标应用、用了什么随机设置和事件偏好
  • 会话标识、开始时间、结束时间和总时长
  • 失败原因、调用上下文原因、monkey 退出码
  • 关键日志尾部、异常统计、证据片段
  • 如果做了日志导出,日志保存到了哪里、总共导出了多少
  • 如果发生运行期异常,具体异常文本是什么

这意味着你可以直接拿这些字段做:

  • 运行中状态感知
  • 时长统计
  • 参数回放
  • 失败排错
  • 结果摘要

其中建议这样理解:

  • 终态原因:
  • 指这轮 monkey 会话最后是怎么结束的
  • 例如正常完成、主动停止、守护收束、离开前台失败
  • 调用上下文原因:
  • 指你这一次查询、等待、停止或清理时处在什么上下文
  • 例如已经在跑、当前没有活跃会话、当前会话正在运行所以不允许清理

不要把两者混用。

怎么理解 ok

这里的 ok 更接近工具运行层是否处于可接受状态,而不是“应用没有任何异常”。

所以要注意:

  • ok=True 不等于“没有 crash / ANR / OOM”
  • 真正的稳定性证据,要继续看 tailstatsevidence
  • 运行中的会话也可能暂时保持 ok=True,这时应优先结合 status 看阶段

换句话说:

  • ok 更接近“这一轮扰动任务是否正常被提交、运行或收束”
  • tail / stats / evidence 更接近“业务稳定性证据”

推荐验收方式

如果你后续把这类扰动纳入回归,建议至少看这几类字段:

  • status
  • monkey_return_code
  • duration_ms
  • tail
  • stats

更稳的判断方式通常是:

  1. 先确认会话已经结束
  2. 再检查 tailstatsevidence 里有没有 crash / ANR / OOM 证据
  3. 必要时结合完整日志导出做额外留证

典型场景

1. 快速冒烟

特点:

  • 小事件量
  • 固定种子
  • 先看有没有明显 crash

2. 稳定性压测

特点:

  • 更长事件数
  • 可能更小的 throttle_ms
  • 重点看 ANR、OOM、崩溃 tail

3. 多设备回归

特点:

  • 不同设备可以带不同的启动意图
  • 统一收集 per-device 结果

实践建议

  • 跑前先确认包名正确
  • 需要复现问题时固定 seed
  • 优先按“启动 -> 状态 -> 等待/停止”的会话方式使用,而不是把它当普通短动作
  • 不要把 ok=True 当成“应用稳定无异常”
  • 如果要深挖异常,再配合:
  • 日志导出
  • 截图留证
  • 媒体侧证据链

风险和限制

  • 当前只暴露一组常用扰动参数,不是完整 adb monkey 全参数面
  • tail 是关键词过滤后的摘要,不是完整日志
  • --pct-appswitch--pct-syskeys 在当前实现里被固定为 0
  • 关键词统计更适合做快速排查,不等于完整问题归因

什么时候优先看这页

  • 你要做稳定性扰动
  • 你要把 Monkey 接入回归链
  • 你在调随机序列、扰动节奏或事件总量
  • 你想知道为什么工具显示成功,但应用其实可能已经异常

相关文档