Android Monkey 笔记

13 阅读9分钟

一、自动化测试全景图:不同维度的守护者

在深入细节之前,我们先看看安卓自动化测试的“全家桶”。不同的测试工具服务于不同的测试目标,我把它们分为四个层级:

测试类型代表工具测试对象目标谁来做
单元测试JUnit, Robolectric方法、类验证单个函数逻辑是否正确开发者
集成测试Espresso, Robolectric组件交互(如Activity与ViewModel)验证多个模块能否协同工作开发者
UI/功能测试Espresso, UI Automator, Appium用户界面、跨应用交互模拟真实用户操作,验证功能是否符合预期QA / 开发者
稳定性/压力测试Monkey, MonkeyRunner整个应用通过暴力随机操作,发现崩溃、ANR、内存泄漏QA / 开发者

今天我们的主角 Monkey,就位于最底层——它是应用的“毁灭者”,通过狂轰滥炸来检验应用的“体质”。

二、Monkey 深度解析:这只“疯狂的猴子”

2.1 Monkey 是什么?

Monkey 是 Android SDK 自带的一个命令行工具,它运行在设备或模拟器中,向系统发送伪随机的用户事件流(如点击、滑动、按键、系统事件等)。你可以把它想象成一只精神亢奋的猴子,在你的应用上毫无章法地乱点乱划,以此来检验应用能否在这种“暴力测试”下存活。

它的核心价值在于:通过随机性和高压力,发现那些常规测试难以覆盖的边缘场景和稳定性问题,比如内存泄漏、ANR、崩溃等

2.2 Monkey 的核心工作原理

Monkey 的本质是一个在设备端运行的 事件生成器。它通过伪随机数生成算法,按照你设定的参数,不断地向系统注入事件。这些事件包括:

  • 触摸事件:点击、长按
  • 手势事件:滑动、轨迹球
  • 导航事件:返回键、菜单键、主页键
  • 系统按键:音量键、相机键
  • 应用启动事件:启动其他 Activity

2.3 Monkey 命令完全指南

Monkey 是通过 adb shell 命令来驱动的。掌握了下面的命令,你就能自如地操控这只“猴子”。

2.3.1 基本命令格式

adb shell monkey [options] <event-count>
  • [options]:配置猴子行为的各种参数。
  • <event-count>:指定发送随机事件的总数 。

2.3.2 常用参数详解

参数示例说明
-p <包名>-p com.example.myapp指定测试的包名。如果不指定,猴子会在整个设备上乱跑,可能会点到其他应用 。
-v-v -v -v指定日志详细级别-v 越多,日志越详细。建议用 -v -v -v 获取最全信息 。
--throttle <毫秒>--throttle 500事件之间的延迟。模拟真实用户操作的间隔,避免操作过快 。
-s <种子值>-s 12345指定随机数生成器的种子。用相同的种子值运行 Monkey,会产生完全相同的随机事件序列。这对于复现和验证 Bug 至关重要
--pct-<事件类型> <百分比>--pct-touch 50调整各类事件的百分比。例如,设置触摸事件占50%,滑动事件占30% 。
--ignore-crashes--ignore-crashes遇到崩溃时不停止。让猴子继续测试,以便发现后续更多问题 。
--ignore-timeouts--ignore-timeouts遇到ANR(应用无响应)时不停止

2.3.3 实战命令组合

场景一:基础稳定性测试 对指定应用发送 10,000 个随机事件,每个事件间隔 300ms,输出详细日志。

adb shell monkey -p com.example.app --throttle 300 -v -v -v 10000

场景二:复现 Bug 使用之前发现 Bug 时的种子值(例如 12345),重新运行测试。

adb shell monkey -p com.example.app -s 12345 --throttle 300 -v 10000

场景三:定制事件类型 模拟以点击为主,夹杂少量滑动的测试场景。

adb shell monkey -p com.example.app --pct-touch 70 --pct-motion 20 --pct-trackball 0 --pct-syskeys 5 --throttle 200 -v 10000

场景四:长时间压力测试(忽略崩溃,持续运行)

adb shell monkey -p com.example.app --ignore-crashes --ignore-timeouts --throttle 300 -v 500000

2.4 如何分析 Monkey 测试结果?

Monkey 跑完之后,最重要的工作是分析日志。我会重点关注以下几个方面:

  1. 搜索关键字:在日志中搜索 CRASHANRExceptionStackOverflowErrorOutOfMemoryError 等关键词 。
  2. 定位堆栈信息:如果发现 Crash,日志中通常会包含 Java 堆栈跟踪(Stack Trace),这能直接告诉你哪个类、哪行代码出了问题。
  3. 记录种子值:一旦发现问题,立刻记录下这次测试的 -s 种子值。这是开发同学修复 Bug 后,用来验证修复是否有效的关键 。
  4. 分析趋势:对于长时间运行(如过夜测试)的 Monkey 结果,可以统计 Crash 次数、ANR 次数,观察应用的内存占用曲线(结合 adb shell dumpsys meminfo),判断是否存在内存泄漏 。

2.5 Monkey 的局限性

Monkey 虽好,但它并不是万能的。作为一个有经验的开发者,我们必须清醒地认识到它的局限 :

  • 测试对象仅为 Activity:Monkey 主要针对 Activity 进行测试,无法直接测试 Service、ContentProvider 等后台组件。
  • 完全随机,无逻辑:它不懂你的业务逻辑。例如,它不会知道必须先登录才能进入个人中心,但这恰恰是它能发现问题的原因——它能触发“未登录就进入个人中心”这种异常路径。
  • 无法模拟复杂场景:无法模拟网络切换、系统低电量、来电中断等真实复杂场景。
  • 无法验证结果:Monkey 只负责“搞破坏”,它不判断操作后的结果是否正确。比如,它点击了“提交”按钮,但不会去验证数据是否成功提交。

因此,Monkey 通常作为“稳定性测试”的第一道防线,用来快速发现那些最底层、最严重的崩溃问题。更深入的业务逻辑验证,需要交给其他工具。

三、其他主流自动化测试框架纵览

在 Monkey 筛选出“能不能活下来”的问题后,我们需要用更精细的工具来验证“功能对不对”。以下是几个我在项目中常用的框架 。

3.1 框架对比

框架类型适用场景优点缺点
EspressoUI 测试单个应用内部的 UI 功能验证Google官方出品,API简洁,与 UI 线程自动同步,执行速度快,支持 View 匹配 。只能测试自己应用内的 UI,无法跨应用。
UI Automator跨应用 UI 测试需要与系统应用(如设置、文件管理器)交互的场景也是官方工具,可以跨应用操作,利用 UI 元素属性进行定位 。测试执行速度比 Espresso 慢。
Appium跨平台 UI 测试同时需要测试 Android 和 iOS 应用的项目跨平台,支持多语言(Java, Python, Ruby等),社区活跃 。架构相对较重,执行速度不如原生框架;需要额外启动 Server。
Robolectric单元测试在 JVM 上快速运行测试,模拟 Android 框架运行速度快,无需真机/模拟器,适合做单元测试和部分集成测试 。只能模拟,不能覆盖所有真实设备特性。

3.2 如何选择?

  • 开发者在写单元测试和集成测试时:首选 JUnit + Robolectric + Espresso 的组合。这是官方推荐且与 Android Studio 集成最好的方案。
  • QA 团队做功能回归测试时:如果是纯 Android 应用,UI Automator 是不错的选择;如果是跨平台应用,Appium 是标配。
  • 做稳定性/压力测试时Monkey 依然是简单高效的入门工具。对于更高级的需求,可以考虑 MonkeyRunner(允许用 Python 写脚本控制)或集成云测试平台(如 Firebase Test Lab)。

3.3 Monkey 与 MonkeyRunner 的区别

这里有个容易混淆的点,顺便说一下:

  • Monkey:是一个程序,直接运行在设备上,生成随机事件流,用于压力测试。
  • MonkeyRunner:是一个工具集,它提供了一个 API,你可以用 Python 写脚本精确控制设备和模拟器,比如截图、安装应用、发送特定按键等,常用于功能测试和回归测试 。

四、实战建议:如何构建自动化测试体系

作为技术负责人,我建议你在项目中分步构建测试体系:

  1. 第一步:引入 Monkey 做“体检”

    • 在每次发版前,安排 Monkey 跑一次“过夜测试”(例如 20万-50万事件)。
    • 将 Monkey 测试集成到 CI(持续集成)流程中,每次打包后自动触发短时间 Monkey 测试(例如 1万事件),快速拦截崩溃 。
  2. 第二步:核心功能用 Espresso 写 UI 测试

    • 对 App 中最核心的业务流程(如登录、下单、支付),用 Espresso 编写 UI 测试用例,确保核心功能永远不出错。
  3. 第三步:关键逻辑用 JUnit + Robolectric 写单元测试

    • 对工具类、数据解析类、复杂逻辑判断等模块,编写单元测试,保证代码的健壮性。
  4. 第四步:引入覆盖率工具

    • 使用 JaCoCo 等工具,查看单元测试和 UI 测试的代码覆盖率,逐步提升测试的全面性。

五、总结

自动化测试不是一蹴而就的,它是一个持续投入、持续受益的过程。作为开发者,我们要理解:

  • Monkey 是你的“敢死队”,负责在最恶劣的环境下检验应用的生存能力。
  • Espresso/UI Automator 是你的“常规部队”,负责守卫核心功能的正确性。
  • 单元测试 是你的“哨兵”,负责在代码层面发现最细微的隐患。

希望这份基于十年经验的梳理,能帮你建立起对安卓自动化测试的全面认知,并让这些工具成为你保障应用质量的得力助手。如果你在具体实施中遇到问题,随时可以再来探讨。