Android 开发自测试 - Monkeyrunner
我们在做 Android 开发自测试的时候除了最基本的 LLT,也可以放出一只野猴子来测试我们的代码健壮性以及程序的稳定性。不过今天我们要当一回驯兽师,训练一只聪明一点儿的猴子 -> Monkeyrunner
为什么要用 Monkeyrunner?
Monkey 工具其实只是一只野猴子,想想你把手机给你三岁儿子玩儿的场景吧,他也就只会一顿瞎摁,操作是没有逻辑性的。所以一般我们实际环境中只会将其作为压力测试的工具。而 Monkeyrunner 干的活可就多了,它就像是你儿子长到 5 岁了,可以让他做一些连贯、需要逻辑处理能力的小事了。
Monkeyrunner 的环境搭建
闲话少说,Monkeyrunner 的环境搭建还是很简单的:
- Android SDK
- Java JDK
- Python
就是这么简单粗暴!
Hello World
下面我们来看一个 Monkeyrunner 版的
Hello World
# Talk is cheap, show me the code.
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
device = MonkeyRunner.waitForConnection()
package = 'com.pioneer.aaron.dolly'
activity = 'com.pioneer.aaron.dolly.MainActivity'
activityToRun = package + '/' + activity
device.startActivity(activityToRun)
MonkeyRunner.sleep(1)
exp_main = device.takeSnapshot()
device.touch(520, 400, MonkeyDevice.DOWN_AND_UP)
MonkeyRunner.sleep(1)
device.press('KEYCODE_BACK', MonkeyDevice.DOWN_AND_UP)
MonkeyRunner.sleep(1)
actual_main = device.takeSnapshot()
print "Return to MainActivity:", exp_main.sameAs(actual_main, 0.9)
# exp_main.writeToFile('~/Desktop/screenshot1.png', 'png')
Monkeyrunner 提供了三个模块,分别为:
MonkeyRunner: 用于连接 Android 设备,真机/模拟器均可;
MonkeyDevice: 用于与设备的交互。操作的事件、安装 APK 什么的都通过它;
MonkeyImage: 镜像?不,真的就是的’图像’,不过这个图像可是 Monkeyrunner 非常重要的一环。
稍微过一下我们上面的代码:
MonkeyRunner.waitForConnection()获取到了我们的设备对象,device.startActivity(activityToRun)启动了一个指定的 Activity,对了这个 APP 在这里,欢迎PR。screenshot = device.takeSnapshot()截了一张图。
这个时候重点来了[敲黑板],MonkeyImage 可以用指定的偏差率来对比像素之间的差异以确定图片的相似性。说中文就是:我们可以用一张期望正确的图片来对比实际的图片,如果一样(误差范围内),那么就证明我们的操作成功了。
在上面的代码中,我点击了一下屏幕 坐标(520, 400),然后按了一下返回键 KEYCODE_BACK,这个时候我们当然期望的是进入返回栈中第二个界面,在这里也就是我们的 MainActivity。然后使用 MonkeyImage.sameAs() 判断返回成功与否。
当然如此简单的一个用例,返回了
$ Return to MainActivity: True
尾巴
以前在学校中写程序,只要能跑起来就行了,充其量是个 DEMO 的阶段,对健壮性、稳定性都不做过多要求。但是现在真正开始写商业软件才发现,一个 NPE 可能就是几条产品线的停工。虽然 Defensive Programming 会让代码看上去面目可憎,但这确实是实际环境中必不可少的一环,这都是无数血泪换来的教训。
当然现在 SDK 已经 自带了 EasyMonkeyDevice 模块,可以让测试代码更加 ‘人性化’ 一点儿。就放在下次再写了吧~