monkey 离线脚本这个标题放在多数人的聊天框里可能第一反应是某个安卓工具的偷懒玩法但真正做稳定性测试的人看到应该会心一笑。这里说的其实就是一套可以脱离人工盯屏、在没有交互式操作的情况下自动完成压力测试注入、运行监控、日志收集和结果归类的完整流程。我最早接触 monkey 是在几年前刚上手 Android 测试的时候那时候跑个压力测试就是直接敲一行adb shell monkey 50000然后盯着终端滚屏滚完数一下有没有崩溃再手动去设备里拉日志。这种玩法放到版本回归、发布前的稳定性验证、甚至 CI 流水线里完全没法用人不可能陪着设备跑三五个小时更不可能同时盯着几十台机器。真正把这件事做好靠的就是把 monkey 跑法和日志策略封装成一套离线脚本让设备脱离人工以后自己完成一切。这篇文章就按照我从需求拆解、命令研究、脚本架构、实操落地到踩坑记录这条线把一套完整的 monkey 离线脚本怎么设计、怎么写、怎么排查问题都展开聊聊。适合刚入行的测试新人、被重复回归折磨的自动化测试同学以及想在持续集成体系里加入稳定性测试能力的团队参考。1. 项目解读离线跑 monkey 到底在解决什么问题1.1 为什么非要把 monkey 变成“离线”的monkey 是 Android 系统自带的一个命令行工具全名叫 UI/Application Exerciser Monkey作用是向设备发送大量的伪随机事件流比如点击、滑动、旋转、缩放、系统按键等用来验证应用长时间运行会不会崩溃、会不会无响应。这个工具本身的用法非常简单但真正投入到实际项目中你会发现几个绕不开的痛点。第一个痛点是时间成本。常规回归测试可能要求跑 5 万、10 万甚至 20 万条随机事件按一般设备的速度跑下来至少需要两三个小时到一晚上。你不可能一直在工位上盯着屏幕更不可能在半夜爬起来做日志归档。只要把执行和日志收集做成了自动离线脚本下班前挂上任务第二天早上直接看报告就行设备在跑人在睡觉互不干扰。第二个痛点是日志的有效性。手动跑 monkey 最容易犯的一个错误是崩溃发生时没有抓到现场日志。monkey 崩溃通过 logcat 可以看到堆栈信息但 logcat 缓冲区是滚动的如果你没有提前做好过滤和归档等到跑完再去翻日志最早的崩溃信息早就被冲掉了。离线脚本的好处在于它能实时监听崩溃事件一旦发现异常就立刻抓取adb bugreport、logcat以及/data/anr/目录下的 trace 文件把现场固定下来。第三个痛点是可复现性。monkey 最大的特点是随机但随机不代表无法控制。每条随机事件序列都基于一个 seed 值生成只要使用相同的 seed 和相同的命令参数就能在另一台设备上复现同样的操作序列。离线脚本的核心价值之一就是把 seed、事件数、事件百分比固定下来保证每次回归的随机序列可追溯、可复现。不然这次的崩溃是随机事件击中某个深藏 bug 导致的你下次随便跑跑不出来这个 bug 就会被漏掉。1.2 离线脚本适合哪些场景从场景划分来看monkey 离线脚本最常用的有三类用途。一类是版本发布前的稳定性验证。新版本提测后测试团队拿一台或一组设备在构建产物上跑一整夜的高强度 monkey观察有没有内存泄漏崩、ANR 频发、IPC 异常这类问题。这类场景对日志完整度和结果分类要求很高因为需要快速定位是哪个模块引发的异常。另一类是竞品对比和回归监控。有的团队会把某应用的历史版本、竞品版本放到同一批设备上用相同 seed、相同事件流跑同样的时间然后对比各自的崩溃率、ANR 次数、内存占用曲线。这种对比测试如果靠人肉操作几乎不可能完成而脚本化之后只需要在配置里切换 APK 路径和包名即可。再有一类是 CI/CD 流水线的集成。很多团队已经把 monkey 离线脚本作为自动化测试任务的一部分打包阶段完成后自动触发一轮烟雾级的 monkey 测试例如跑 1 万事件如果崩溃率超过阈值流水线直接标红。这种场景下脚本不需要交互只需要一个命令行入口、一个固定的退出码和一份机器可读的报告。2. 技术底座把 monkey 命令参数吃透2.1 参数不是随便填的先理解玩法的可组合性monkey 的命令格式虽然简单但参数组合非常多不同组合的测试目的完全不同。很多新手喜欢直接adb shell monkey 50000把默认参数跑满最后崩溃一堆也不知道是哪个动作触发的。我建议在做离线脚本之前先把下面这张常用参数表过一遍按真实需求去选。参数作用实际用法-p指定包名-p com.demo.app限定只测试目标应用不写会整个系统乱跑-s指定种子值-s 1687保证随机序列可复现--throttle事件间隔毫秒--throttle 300表示每个事件之间停顿 300ms-v日志详细级别-v -v -v输出最详细的事件、崩溃信息--pct-touch触摸事件占比--pct-touch 40设置触摸事件占 40%--pct-motion滑动事件占比--pct-motion 25--pct-appswitch应用切换占比--pct-appswitch 10模拟用户后台切换--pct-syskeys系统按键占比--pct-syskeys 5模拟 Home、返回等按键--ignore-crashes崩溃后继续运行遇到崩溃不中止跑完整个事件流--ignore-timeoutsANR 后继续运行遇到 ANR 不中止--kill-process-after-error出错后杀死应用进程设置后下次事件从新进程开始--monitor-native-crashes监听原生层崩溃监控 so 层崩溃需要加上--bugreport崩溃时自动抓取报告每次崩溃自动尝试抓取adb bugreport--dbg-no-events不发送事件仅启动应用可用于初始化安装验证这些参数看起来零散但是组合起来就是测试策略。比如我需要做一次偏向用户操作习惯的标准回归我会把触摸和滑动压到 60% 以上同时留一部分给应用切换和系统按键来模拟真实用户频繁切换页面的过程。如果我是偏向做异常状态验证比如来电打断、低电量提示这类场景就要调高--pct-syskeys和--pct-appswitch的占比同时配合其他指令。2.2 用 seed 锁定随机序列把概率变成可复现seed 可以说是 monkey 测试里最容易被忽略但是最重要的参数。我的经验是任何一次正式测试都要显式指定 seed。为什么要这么做因为 monkey 的随机事件发生器是一个伪随机算法给定相同的 seed它生成的事件序列是相同的。种子不同跑的路径完全不同很多崩溃只有特定的种子序列才能触发。举个例子。假设当前版本在手势滑动某个页面时偶发崩溃但你随机跑 10 万事件没有复现这时候最好的做法不是加大数量盲目撞概率而是保住当前现场的 seed。现场日志里会记录当时用的 seed 值下次直接用这个 seed 搭配相同的参数和包名版本重新跑大概率可以复现问题然后交给开发定位。离线脚本里必须把这个 seed 自动化落盘并且报告里带上有用的现场索引。我在工作里习惯约定 seed 的生成策略如果是日常轮询回归用固定的常用 seed比如 10086保证每轮测试事件序列一致方便横向对比如果是独立验证测试使用时间戳生成 seed避免每次跑的都是同一条路径发现问题的覆盖面更广。无论哪种策略最后的报告里一定要能追溯到 seed 和完整命令。2.3 事件百分比设置的思路不是拍脑袋事件百分比直接决定测试压力作用在哪些交互行为上。很多人偷懒直接不写--pct-*结果系统默认的事件分布跟你期望的完全不一样。默认 monkey 的触摸、滑动等事件占比是各占一部分但系统按键和导航事件也占有相当比例实际体验下来会感觉操作很“乱”容易误触一些系统界面。我的建议是先用执行任务表把期望的事件分布写清楚再换算成百分比。假设我要做一次电商类应用的稳定性验证用户行为主要集中在浏览商品、滑动列表、点击加购、切换 Tab、偶尔退出到桌面。那么对应的事件模型我会设置触摸 45%、滑动 30%、应用切换 10%、系统按键 5%、其他事件缩放、旋转等10%。这样跑出来的路径比较接近真实用户的操作节奏而不是像无头苍蝇一样在系统各个页面乱跳。如果目标是验证多进程或者后台服务稳定性我会降低触摸和滑动的占比提高系统按键和应用切换占比模拟用户反复切后台、唤起其他应用观察目标进程是否被杀、是否产生 ANR。不同测试目标要匹配不同的参数模板这套模板要提前沉淀在离线脚本的配置文件中而不是每次临场手敲。3. 脚本设计拆成模块之后逻辑一下就清楚了3.1 离线脚本应该具备哪些能力很多人以为一个 monkey 离线脚本就是一行adb shell monkey加一个日志重定向这个理解太浅了。真正能上生产的脚本至少应该具备下面几项能力。第一是设备连接管理。要能自动检测连接的设备支持指定序列号、多设备并发、设备断开后的重试逻辑。第二是前置条件处理。安装指定 APK、设置权限、清理应用数据、关闭系统自动更新等干扰因素。第三是 monkey 执行控制。包括命令构造、事件数量、seed、超时控制、执行状态统计。第四是日志采集与归档。实时抓取 logcat、崩溃栈、ANR trace、bugreport等按时间戳和场景目录归档。第五是报告生成。用统一格式输出执行概要、崩溃列表、崩溃详细信息、内存趋势等方便后续人工判断和团队周报。基于这个清单我在实际项目里通常把离线脚本拆成两个大的部分负责跑流程的外层控制脚本和负责数据后处理的 Python 分析模块。外层控制脚本用 shell 或者批处理编写在 Linux 执行机上负责多设备调度、超时控制、简单轮询、日志粗分类Python 部分负责解析logcat里的崩溃关键字、聚合 ANR 信息、生成可读的 HTML 文本报告。这套结构的好处是逻辑清晰外壳坏了可以直接改壳分析逻辑变更不需要动执行层。3.2 日志目录设计和文件名规则的讲究日志目录是我踩过最多坑的地方。没有一套规范的目录日志采集回来以后根本没法快速定位问题。我现在的标准做法是在每个设备的测试根目录下按设备序列号_日期_测试轮次建目录内部再细分子目录。output/ 192.168.1.10_20250614_001/ installd.log # 安装与前置步骤日志 monkey.log # monkey 标准输出 logcat_main.log # 主 logcat 全量日志 logcat_crash.log # 实时过滤的崩溃日志 events.log # monkey --bugreport 生成的事件细节 traces/ # ANR trace 文件 001_crash_com.demo.app.log 001_anr_com.demo.app.log report.txt这个结构的好处是后续无论是人工排查还是写自动化分析工具都能基于确定的路径找到对应文件。文件名加了序号后崩溃发生的顺序一目了然。我曾经遇到一个团队把崩溃日志全部堆到一个目录里文件名又是纯时间戳排查问题时翻了整整一小时效率极低。3.3 崩溃监听和 ANR 采集要主动抓别只依赖重定向这是整个离线脚本里技术含量最高的部分。直接把adb shell monkey的输出重定向到文件只是最基础的日志保存真正关键的是实时日志采集。我通常会在脚本里同时开一个后台循环持续执行adb logcat -v threadtime抓取实时日志并且在抓取的同时用关键词过滤崩溃信息。常见的关键词包括FATAL EXCEPTION、ANR in、am_anr、am_crash、嵌入式场景还要看SIGSEGV、SIGABRT这类信号量。一旦检测到崩溃立即复制当前logcat缓冲区的关键片段同时尝试从设备上拉取/data/anr/目录下新的 trace 文件。这里要注意抓取 ANR 文件需要 root 权限或者使用adb bugreport来间接获取直接在 shell 里adb pull /data/anr/经常会失败这也是后面问题排查要展开的部分。这样的主动监听方式比等 monkey 跑完再统一分析要好得多因为崩溃现场有大量瞬时信息比如事件序列、内存快照、CPU 状态过了这个时机就再也拿不到了。4. 实操过程一份能直接上手的 monkey 离线脚本4.1 前置准备与运行环境动手写脚本之前先把执行环境准备好。macOS 或者 Linux 上安装好 adb 工具Windows 上建议在 PowerShell 或者转换为 shell 兼容环境运行不过我当时直接用的 Ubuntu 执行机配合多台 Android 设备通过 USB 或者 Wi-Fi adb 连接管理。执行前确认设备开启开发者模式并且已授权adb调试运行adb devices能看到所有设备。为了让脚本可以灵活切换测试目标我在脚本目录下放了一个config.env配置文件集中管理包名、APK 路径、事件数、seed、事件百分比、执行时长上限这些参数。离线脚本的灵活性全部归功于把可变项收敛到配置文件中不用为了每类测试都去改代码本体。PACKAGEcom.demo.app APK_PATH./app-release.apk EVENT_COUNT50000 SEED10086 THROTTLE300 TOUCH_PCT45 MOTION_PCT30 APP_SWITCH_PCT10 SYSKEYS_PCT5 TIMEOUT_SEC72004.2 脚本主体shell 部分的管理与控制逻辑外层脚本主要完成设备选择、APK 安装、日志目录准备、monkey 命令构造、超时控制和基础日志轮转。这里有一个关键点是执行 monkey 命令时要使用timeout命令包裹防止因为某些异常事件导致进程挂起而无限等待。monkey 自身有事件数量限制但事件之间如果某个--throttle值设置得太小遇到页面动画卡顿事件注入速度会受影响实际耗时会比你预想的长很多。超时控制必须要有否则 CI 任务会把执行机长时间占住。#!/bin/bash source ./config.env ADBadb DEVICE_ID$1 if [ -z $DEVICE_ID ]; then echo Usage: $0 device-id exit 1 fi # 输出目录构建 BASE_DIR./output/${DEVICE_ID}_$(date %Y%m%d_%H%M%S)_${SEED} mkdir -p $BASE_DIR/traces run_cmd() { $ADB -s $DEVICE_ID $ } # 安装与系统预处理 run_cmd install -r $APK_PATH $BASE_DIR/installd.log 21 run_cmd shell am force-stop $PACKAGE run_cmd shell pm clear $PACKAGE # 构造 monkey 命令参数 CMD$ADB -s $DEVICE_ID shell monkey -p $PACKAGE -s $SEED \ --throttle $THROTTLE \ --pct-touch $TOUCH_PCT \ --pct-motion $MOTION_PCT \ --pct-appswitch $APP_SWITCH_PCT \ --pct-syskeys $SYSKEYS_PCT \ --ignore-crashes \ --ignore-timeouts \ --monitor-native-crashes \ -v -v -v \ $EVENT_COUNT # 启动实时 logcat 采集 run_cmd logcat -c run_cmd logcat -v threadtime $BASE_DIR/logcat_main.log 21 LOGCAT_PID$! # 执行 monkey加超时控制 timeout $TIMEOUT_SEC $CMD $BASE_DIR/monkey.log 21 MONKEY_EXIT$? # 停止 logcat 采集 kill $LOGCAT_PID 2/dev/null # 基础崩溃关键词提取 grep -n -E FATAL EXCEPTION|ANR in $BASE_DIR/monkey.log $BASE_DIR/crash_hint.log echo $MONKEY_EXIT $BASE_DIR/exit_code.txt exit $MONKEY_EXIT这段 shell 脚本的思路很直接安装、清数据、构造命令、后台日志、超时执行、崩溃关键词初筛。执行完以后立即把退出码和崩溃摘要存到固定位置方便后续汇总。这里--ignore-crashes和--ignore-timeouts我刻意加上因为目标不是遇到一次崩溃立刻中止而是让 monkey 持续跑完整个压力周期把所有问题都暴露出来。如果你想尽早暴露并停止可以把这两个参数去掉。4.3 Python 后处理从日志到可读报告Shell 负责跑Python 负责分析和归档。这部分我写了一个简单的日志解析器读取crash_hint.log、monkey.log和logcat_main.log按崩溃类型分类并尝试提取崩溃发生的具体堆栈片段。核心逻辑是在logcat_main.log里定位FATAL EXCEPTION出现的位置然后从该行往后找一段包含at com.demo.app的调用栈输出到独立文件。import os import re import sys from collections import defaultdict def parse_monkey_log(monkey_log_path): lines open(monkey_log_path, encodingutf-8, errorsignore).readlines() result {crashes: 0, anr: 0, finished: 0, events: 0} for idx, line in enumerate(lines): if FATAL EXCEPTION in line or Process: in line: result[crashes] 1 if ANR in in line: result[anr] 1 if Events injected in line: m re.search(rEvents injected: (\d), line) if m: result[events] int(m.group(1)) if Monkey finished in line: result[finished] 1 return result def extract_crash_stack(logcat_path, output_dir): lines open(logcat_path, encodingutf-8, errorsignore).readlines() count 0 for idx, line in enumerate(lines): if FATAL EXCEPTION in line or ANR in in line: count 1 file_name f{count:03d}_crash.txt target os.path.join(output_dir, file_name) with open(target, w, encodingutf-8) as f: end min(idx 80, len(lines)) f.writelines(lines[idx:end]) print(f[extract] {file_name}) return count if __name__ __main__: base sys.argv[1] stats parse_monkey_log(os.path.join(base, monkey.log)) crash_files extract_crash_stack(os.path.join(base, logcat_main.log), os.path.join(base, traces)) with open(os.path.join(base, report.txt), w, encodingutf-8) as f: f.write(fcrashes: {stats[crashes]}\n) f.write(fanr: {stats[anr]}\n) f.write(fevents: {stats[events]}\n) f.write(ffinished: {stats[finished]}\n) f.write(fextracted_crash_files: {crash_files}\n)这段代码有个细节崩溃栈片段提取不是简单地把整段日志都复制到崩溃文件而是只取崩溃点之后的 80 行。因为 logcat 在崩溃发生后往往紧接着出现大量新事件太多无关日志会干扰定位。80 行是我在实际使用中觉得比较合适的窗口基本覆盖从FATAL EXCEPTION到at com.demo.app的完整 Java 堆栈又不至于把后续无关日志带进来。4.4 多设备并发的调度思路生产环境里很少只跑一台设备多设备并发是标配。最简单可靠的并发方案是循环逐个设备执行上面那个 shell 脚本但这里有个问题adb 多设备命令不加-s参数时它会报错或者默认选择第一台设备造成执行混乱。需要在最外层写一个调度脚本来遍历adb devices输出的设备列表并为每个设备启动一个后台任务。#!/bin/bash adb devices | awk NR1 {print $1} | while read dev; do if [ $dev ! ]; then echo start monkey on $dev ./run_monkey.sh $dev fi done wait echo all device tasks completed多设备并发时要额外注意执行机的串口带宽和 USB 资源。如果设备数量较多建议给每台设备的 adb 连接加一个server级配置同时限制同时拉取日志的数量。日志拉取是 IO 密集操作我曾经一次并发 16 台设备拉取 bugreport结果把执行机的磁盘 IO 打满所有任务的写入速度都明显下降。后来我在调度脚本里对设备分批处理同一批次最多 4 台进入日志拉取流程其他设备先等待整体效率反而更高。5. 常见问题与排查技巧实录5.1 monkey 跑完了日志目录里却什么都没有遇到这个问题第一反应不是脚本出问题了而是先看设备是否真的执行了命令。很多情况下是因为安装失败或者包名不匹配导致 monkey 根本启动不了目标应用。检查installd.log是否有Success再手动执行一下adb shell monkey -p 包名 1看返回输出。我遇到过一次比较隐蔽的问题是测试 APK 和当前设备 Android 版本的 targetSdk 冲突安装能够成功但启动时直接崩溃monkey 还没开始注入事件应用就已经死了。这时候 monkey.log 里通常会有Error launching activity的字样。另一个常见原因是 logcat 后台进程没有正确启动。你要确认脚本里adb logcat是否用了后台符号以及执行完 monkey 后是否把该进程 kill 掉。如果上一轮的 logcat 进程没清理当前轮的日志会写到上一个进程对应的文件你打开当轮目录自然什么都看不到。5.2 崩溃日志抓到了但 ANR trace 始终拉取失败这是没有 root 的设备上最常见的坑。Android 系统的/data/anr/目录权限受限普通 adb 权限无法直接访问。很多测试员在脚本里写adb pull /data/anr/然后发现 Permission denied就以为拿不到 ANR 现场了。其实可以用两个替代方案。第一个是在 monkey 命令里带--bugreport参数崩溃或 ANR 时可以自动触发 bugreport 收集/data/anr/下的信息。第二个是升级为adb bugreport手动采集它能把系统所有诊断信息打包到执行机里面通常包含traces.txt。我的离线脚本在检测到 ANR 关键词时会额外调用一次adb bugreport来导出系统 snapshot虽然耗时较长但采集到的信息量比单独拉 ANR 目录全面得多。要注意的是adb bugreport本身耗时可能超过一分钟如果 ANR 触发频繁采集计划要做好超时和频率控制避免日志还没拉完设备已经被下一轮事件继续冲击。5.3 monkey 命令卡住不动超时后杀不掉进程有时候timeout虽然能杀掉 adb 命令但设备里的 monkey 进程可能还在跑继续消耗系统资源。此时你要在 shell 脚本的超时处理分支里补一步清理设备端进程adb shell pkill -f monkey但注意pkill不是所有 Android 设备都内置。更通用的做法是先查 monkey 进程的 PID再adb shell kill -9 PID。我一般会在脚本里封装一个函数在timeout返回非零退出码时主动执行一次进程清理。这样下一轮测试开始前设备是干净的不会出现前一个 monkey 的事件流还留在系统里干扰新一轮测试的情况。5.4 崩溃率很高但人工复看日志发现都是同一个误报monkey 崩溃日志里的内容不都是应用代码的 bug也可能来自系统组件。比如某些设备在低内存条件下会触发系统桌面重启日志里会看到systemui的 FATAL EXCEPTION但它跟目标应用无关。离线脚本的分析模块一定不能被所有崩溃关键词骗到要在报告里按进程名分类统计。我的做法是在extract_crash_stack里把崩溃进程名也解析出来与目标包名做匹配。只把与目标包名相关的崩溃标记成有效崩溃系统级崩溃单独列一份统计便于处理。这样做能大幅减少报告噪音。实际项目里我见过有团队因为统计了系统桌面崩溃误报率高达 60%开发复查后全是无效单后面自动化可信度受到很大影响。现象排查方向处理建议日志目录为空adb 连接、安装失败、包名不匹配检查 installd.log、单步手动执行ANR 无法拉取/data/anr 权限不足使用 --bugreport 或 adb bugreport 兜底monkey 卡死事件流异常、低内存timeout 包裹pkill 进程清理崩溃率虚高系统进程崩溃被统计按进程名过滤只统计目标包多设备并发拉日志慢USB/磁盘 IO 瓶颈分批拉取、限制同批设备数量5.5 报告里的退出码含义要准确解读monkey 命令退出码不是随随便便看的。按照我的经验退出码 0 表示 monkey 执行完毕退出码非 0 则多半是发生了中断或者错误但这里有个细节即使加了--ignore-crashesmonkey 仍然可能因为其他异常返回非零退出码。例如设备存储满导致日志写不进去、adb 连接断开、设备进入休眠锁屏等都会让命令提前结束。你不能简单认为退出码非 0 就是被测应用出现了崩溃应该结合monkey.log里的Monkey aborted due to error这类文本做二次确认。这里分享一个排查技巧在日志里搜索** Monkey aborted due to error后面紧跟的原因字段它通常直接告诉你是什么触发了中断。我之前遇到过几次设备屏保导致事件无法注入就是通过这个字段定位到的。处理方法是提前设置设备亮屏时间无限长并在脚本执行前通过svc power stayon true强制保持唤醒。5.6 顺手总结三个独家小技巧脚本里所有临时文件命名都要带设备和 seed别只带时间戳。多设备并发状态下不同设备的日志如果文件名重复输出目录一合并直接互相覆盖这类事故发生过不止一次。monkey 的阈值和判定标准要固化不要每次跑完再人肉定标准。最好的方式是在配置里写清楚“崩溃次数大于等于 1 就标红”同时允许人工在后处理报告里备注无效崩溃。自动化结果如果不带人工复核通道时间长了大家会对红色告警麻木最终这个工具会被团队弃用。日志分析时不要忽略Events injected这个字段。它显示实际注入的事件数量。如果配置问 5 万事件但它只注入了 1 万就收到系统中断说明测试并没有达到预期压力强度即使是退出码 0 也要引起注意。6. 这套脚本后续还能往哪个方向扩展monkey 离线脚本做到一定程度之后瓶颈往往不在脚本本身而在如何把结果和研发流程打通。我目前比较喜欢的方向是把离线脚本的产出标准化为 JSON 格式然后对接团队内部的看板系统每次测试完成自动推送一条消息包含崩溃摘要、趋势变化、复跑入口。这样稳定性测试的结果不只是跑完自己看看而是能实时暴露给整个团队。另一个扩展方向是接入内存监控。压力测试如果只看崩溃和 ANR很多内存泄漏问题会被漏掉因为这些泄漏往往不会在短时间内触发崩溃。可以在外部脚本里周期性执行adb shell dumpsys meminfo 包名记录内存曲线跑完以后对照事件流定位是哪个阶段导致的内存激增。这块我当时没有写进第一版脚本后面单独花了一个迭代周期补上效果很好。如果你所在的团队已经有统一调度平台还可以把这套 shell 脚本封装成可执行任务做成参数化驱动。比如传入 APK 下载地址、包名、测试时长平台自动分配设备和存储空间。脚本本身保持简单把复杂调度交给平台脚本只负责“跑设备相关的脏活累活”。回到最开始的那个问题。monkey 离线脚本本质上是把测试员从重复劳动里解放出来的工具但工具能发挥多大价值取决于使用者对 monkey 参数、日志语义和设备行为的理解深度。能跑通一条命令很容易能把崩溃现场完整地带回来并在团队协作中形成闭环才算真的把离线脚本做成了项目里靠谱的基础设施。
阅读完成 · 觉得有帮助?