手动回归测试最让人头疼的,不是测试本身,而是把相同的点击、输入、滑动重复几十遍。MonkeyRunner 正好能把这套动作交给脚本执行。它随 Android SDK 一起发布,位于 tools 目录下,通过 Jython 解释器运行 Python 2 语法的脚本,底层利用 adb 通道向设备或模拟器发送事件。脚本编写门槛不高,只要能看懂 Python 基础语法,就能快速上手。

MonkeyRunner 的核心由三个类组成:MonkeyRunner 负责脚本入口与设备等待,MonkeyDevice 代表一台已连接的设备或模拟器,MonkeyImage 用来处理截图和图像对比。开发者调用这些 API 即可实现安装应用、启动 Activity、发送按键、模拟触摸、拖拽滑动、执行 shell 命令、保存截图等操作。与 JUnit 或 Espresso 不同,它不关心应用内部 View 层级,只从屏幕坐标和系统事件层面驱动,因此非常适合做冒烟测试和跨应用交互测试。
环境准备与首个连接脚本
使用 MonkeyRunner 前需要安装 JDK 和 Android SDK,并把 SDK 目录下的 tools 和 platform-tools 加入系统环境变量。Windows 下典型路径是 C:\Android\SDK\tools 和 C:\Android\SDK\platform-tools,Linux 或 macOS 则对应解压目录。配置完成后,在命令行输入 monkeyrunner 能看到 Jython 交互提示符,说明环境就绪。MonkeyRunner 脚本文件通常以 .py 结尾,运行时直接执行 monkeyrunner script.py。
连接设备是脚本的第一步。MonkeyRunner.waitForConnection() 会阻塞直到有设备通过 adb 连接,返回一个 MonkeyDevice 对象。如果电脑上同时连接多台设备,可以给 waitForConnection 传入设备序列号参数,避免脚本操作到错误的机器。连接成功后,通过 getProperty 可以读取系统版本、厂商等基础信息,方便在日志中确认目标设备。
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
# 等待设备连接,默认返回第一台可用设备
device = MonkeyRunner.waitForConnection()
# 打印系统版本和设备型号
print "Android version: " + device.getProperty("build.version.release")
print "Device model: " + device.getProperty("build.model")
这段代码只有几行,却能验证整个链路是否通畅。如果控制台输出了版本号和型号,说明 JDK、SDK、adb、MonkeyRunner 四者协作正常。接下来就可以开始注入事件了。需要注意的是,MonkeyRunner 基于 Jython 2.7,语法上遵循 Python 2 规范,print 语句可以不带括号,字符串拼接使用加号也很常见。
核心事件注入:按键、输入与触控
MonkeyDevice 提供了一系列真实设备操作接口。press 方法用于发送系统按键,例如返回键、Home 键、音量键。第一个参数是按键名称,第二个参数是动作类型,DOWN 表示按下,UP 表示抬起,DOWN_AND_UP 表示一次完整点击。type 方法负责向当前焦点输入文本,对已获得焦点的输入框非常有效。touch 方法则直接针对屏幕坐标模拟点击,传入横纵坐标和动作类型即可。
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
device = MonkeyRunner.waitForConnection()
# 启动系统设置应用
device.startActivity(component="com.android.settings/.Settings")
MonkeyRunner.sleep(2)
# 模拟一次返回键点击
device.press('KEYCODE_BACK', MonkeyDevice.DOWN_AND_UP)
# 在焦点输入框中输入文本
device.type("hello monkey")
# 点击屏幕坐标 (200, 400)
device.touch(200, 400, MonkeyDevice.DOWN_AND_UP)
startActivity 方法可以直接拉起任意 Activity,component 参数使用包名和类名组合。相比手动打开应用,这种方式能跳过启动器页面的不确定性。drag 方法用于模拟滑动,可以指定起点、终点、持续时间和步数,常用于翻页或者下拉通知栏。shell 方法则直接执行 adb shell 命令,例如实现屏幕常亮、杀掉进程等系统级操作。
事件注入的本质是把脚本调用翻译成 adb shell input keyevent 或 input tap 等命令,再通过 adb 通道发送给设备端。因此每次操作都存在一定的网络开销,连续大量点击时速度会比 Espresso 这类直接运行在设备内的框架慢。但对于回归测试而言,稳定性远胜于人工操作,速度通常可以接受。实际使用中建议在关键步骤之间调用 MonkeyRunner.sleep() 增加等待,避免页面未加载完成就执行下一步造成误操作。
截图与图像对比在断言中的运用
MonkeyRunner 静态断言能力主要靠截图对比。MonkeyImage 对象通过 device.takeSnapshot() 获得,代表当前屏幕的位图。writeToFile 可以把截图保存到本地,路径需要写绝对路径,Windows 下注意反斜杠转义。sameAs 方法用于比较两张图片的相似度,第二个参数是相似度阈值,范围 0 到 1,1 表示完全一致。当界面发生细微变化时,可以把阈值适当调低,比如 0.9 或 0.85。
# 截图并保存到本地
image = device.takeSnapshot()
image.writeToFile("C:\\monkey\\screen.png", "png")
# 抬起屏幕后再次截图,比较是否发生变化
image1 = device.takeSnapshot()
MonkeyRunner.sleep(1)
device.press('KEYCODE_HOME', MonkeyDevice.DOWN_AND_UP)
MonkeyRunner.sleep(1)
image2 = device.takeSnapshot()
if image1.sameAs(image2, 0.9):
print "画面未发生明显变化"
else:
print "检测到界面切换"
截图对比适合验证页面跳转、弹窗消失、按钮状态改变等场景。不过它只比较像素级相似度,无法判断具体文字内容是否正确。如果被测界面中动态元素过多,例如时间栏、电量图标频繁刷新,很容易导致误报。此时可以利用 getSubImage 截取屏幕上相对稳定的子区域,再对子图进行对比,从而避开动态区域的干扰。
综合脚本实战与局限性分析
下面把前面的知识点串联起来,完成一个简单的 UI 冒烟测试脚本:启动设置应用,向上滑动列表,点击第一个可点击项,最后截图保存并输出完成信息。这个脚本没有断言,主要用于演示流程控制。实际项目中可以在关键步骤后加入截图和 sameAs 校验,形成完整的自动化测试闭环。
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
device = MonkeyRunner.waitForConnection()
# 启动设置
device.startActivity(component="com.android.settings/.Settings")
MonkeyRunner.sleep(3)
# 从屏幕下方往上滑动,模拟翻动设置列表
device.drag((300, 900), (300, 300), 0.3, 5)
MonkeyRunner.sleep(1)
# 点击屏幕中部一个列表项
device.touch(300, 500, MonkeyDevice.DOWN_AND_UP)
MonkeyRunner.sleep(2)
# 截图保存
shot = device.takeSnapshot()
shot.writeToFile("C:\\monkey\\smoke_test.png", "png")
print "smoke test finished"
MonkeyRunner 的短板同样明显。它依赖 Jython 2.7,而 Python 2 已经停止维护,新语法和新库无法使用。事件注入只支持坐标和按键,难以处理复杂手势,比如双指缩放。它也不能直接获取 View 树或控件属性,无法实施基于语义的定位与断言。在多设备并行方面,MonkeyRunner 只能一次连接一台设备,若要在多台机器上并发执行,需要自行管理多进程。
所以 MonkeyRunner 更适合作为补充工具,在简单冒烟测试、跨应用操作、安装卸载冒烟等场景中保持轻量高效。如果项目需要长期维护,建议同时评估 Appium、UI Automator 或 Espresso。Appium 支持 WebDriver 协议和多种语言,UI Automator 能获取控件信息,Espresso 则在单应用内提供极快的执行速度。把 MonkeyRunner 定位为快速验证和临时调试工具,往往比强行用它搭建完整测试体系更加合理。
MonkeyRunnerAndroid自动化测试Jython修改时间:2026-10-02 23:09:21