# Monkey文档
# 一. Monkey基础知识
# 1.1 Monkey概况
Monkey是Google提供的一个命令行工具,可运行在模拟器或实际设备中。它向系统发送伪随机的用户事件,模拟用户的按键输入、触摸屏输入、手势输入等,从而对正在运行的应用程序进行压力测试,目的是看设备多长时间会出现异常,并观察系统的稳定性和容错性能。官网
Monkey程序是Android系统自带的,其启动脚本是位于Android系统的/system/bin目录的Monkey文件,其jar包是位于Android系统的/system/framework目录的Monkey.jar文件。用户主要是通过adb 命令来启动Monkey的。同时,Monkey还会对测试系统进行监测,当出现以下三种情况时会进行特殊处理:
- 如限定了Monkey运行在特定包上,当监测到试图转到其他包的操作,将对其进行阻止。
- 如应用程序崩溃或接收到任何失控异常,Monkey将记录对应的错误日志,并根据命令行参数判断是停止运行还是继续运行。
- 如果应用程序发生了程序无响应(application not responding)的错误,Monkey将记录对应的错误日志,并根据命令行参数判断是停止运行还是继续运行。
# 1.2 Monkey参数
Monkey启动命令行脚本为:
monkey [options] <count>
其中,options表示Monkey执行的可配置参数,是可选项(如果不指定options,Monkey将以无反馈模式启动,并把事件任意发送到安装在目标环境中的全部包);count表示Monkey执行的事件数,为必选项。
option可分为五类:
- 基本配置类参数
--help 打印一个简单的使用指南
-v 用于指定反馈信息级别,也就是日志的详细程度,分Level0、Level1、Level2;-v 默认值,仅提供启动提示,操作结果等少量信息 ,也就是Level0,比如adb shell monkey -p xxx.xxx.xxx -v 1 ;-v -v 提供比较详细信息,比如启动的每个activity信息 ,也就是Level21,比如adb shell monkey -p xxx.xxx.xxx -v -v 1 ;-v -v -v 提供最详细的信息 ,比如adb shell monkey -p xxx.xxx.xxx -v -v -v 1
- 事件类型和频率参数
-s < seed > 伪随机数生成器的种子值,如果我们两次monkey测试事件使用相同的种子值,会产生相同的事件序列;如果不指定种子值,系统会产生一个随机值。种子值对我们复现bug很重要。使用如下adb shell monkey -p xxx.xxx.xxx -s 11111 10;这也是伪随机事件的原因,因为这些事件可以通过种子值进行复现
--throttle < 毫秒 > 设置每个事件结束后延迟多少时间再继续下一个事件,降低cpu压力;如果不设置,事件与事件之间将不会延迟,事件将会尽快生成;一般设置300ms,因为人最快300ms左右一个动作,比如 adb shell monkey -p xxx.xxx.xxx -v -v -v --throttle 300 10
--pct-touch < percent > 设置触摸事件的百分比,即手指对屏幕进行点击抬起(down-up)的动作;不做设置情况下系统将随机分配各种事件的百分比。比如adb shell monkey -p xxx.xxxx.xxx --pct-touch 50 -v -v 100 ,这就表示100次事件里有50%事件是触摸事件
--pct-motion < percent > 设置移动事件百分比,这种事件类型是由屏幕上某处的一个down事件-一系列伪随机的移动事件-一个up事件,即点击屏幕,然后直线运动,最后抬起这种运动
--pct-trackball < percent > 设设置轨迹球事件百分比,这种事件类型是一个或者多个随机移动,包含点击事件,这里可以是曲线运动,不过现在手机很多不支持,这个参数不常用
--pct-nav < percent > 设置基本的导航按键事件百分比,比如输入设备上的上下左右四个方向键
--pct-majornav < percent > 设置主导航事件的百分比,(这些导航事件通常会引起你的UI中的动作,如在5路垫中心按钮,返回键或菜单键)。
--pct-syskeys < percent > 设置系统物理按键事件百分比,比如home键,音量键,返回键,拨打电话键,挂电话键等
--pct-appswitch < percent > 设置monkey使用startActivity进行activity跳转事件的百分比,保证界面的覆盖情况
--pct-anyevent < percent > 设置其它事件百分比,这是一个包罗万象的所有其他类型的事件,如按键,设备上的其他不常用的按键,等等
- 约束限制类参数
-p < 允许包名称 > 用于约束限制,用此参数指定一个包,指定包后Monkey将被允许启动指定应用;如果不指定包, Monkey将被允许随机启动设备中的应用(主Activity有android.intent.category.LAUNCHER 或android.intent.category.MONKEY类别 )。比如 adb shell monkey -p xxx.xxx.xxx 1 ; xxx.xxx.xxx 表示应用包名,1 表示monkey模拟用户随机事件参数,最低1,这样就能把应用启动起来
-c < 主类别 > 指定Activity的category类别,如果不指定,默认是CATEGORY_LAUNCHER 或者 Intent.CATEGORY_MONKEY;不太常用的一个参数
- 调试类参数
--dbg-no-events 指定后,Monkey 将初始启动到测试 Activity,但不会生成任何其他事件。 为了获得最佳结果,请结合使用 -v、一个或多个软件包约束条件以及非零限制,以使 Monkey 运行 30 秒或更长时间。这提供了一个环境,您可以在其中监控应用调用的软件包转换操作
--hprof 如果设置此选项,则会在 Monkey 事件序列之前和之后立即生成分析报告。这将在 data/misc 下生成大型(约为 5Mb)文件,因此请谨慎使用。如需了解如何分析性能分析报告,请参阅分析应用性能
--ignore-crashes 通常,当应用崩溃或遇到任何类型的未处理异常时,Monkey 将会停止。如果指定此选项,Monkey 会继续向系统发送事件,直到计数完成为止
--ignore-timeouts 通常,当应用遇到任何类型的超时错误(例如“应用无响应”对话框)时,Monkey 将会停止。如果指定此选项,Monkey 会继续向系统发送事件,直到计数完成为止
--ignore-security-exceptions 通常,当应用遇到任何类型的权限错误(例如,如果它尝试启动需要特定权限的 Activity)时,Monkey 将会停止。如果指定此选项,Monkey 会继续向系统发送事件,直到计数完成为止
--kill-process-after-error 通常,当 Monkey 因出错而停止运行时,出现故障的应用将保持运行状态。设置此选项后,它将会指示系统停止发生错误的进程。 注意,在正常(成功)完成情况下,已启动的进程不会停止,并且设备仅会处于最终事件之后的最后状态
--monitor-native-crashes 监视并报告 Android 系统原生代码中发生的崩溃。如果设置了 --kill-process-after-error,系统将会停止
--wait-DBG 指阻止 Monkey 执行,直到为其连接了调试程序
- 官方隐藏类参数
--pkg-blacklist-file < 黑名单文件 > 限制 Monkey 不测试于指定黑名单文档中记录的包。若没有使用这个参数,Monkey 会测试系统内所有的包。若使用了该参数,可通过在黑名单文档内记录所有不要测试的包名称,来限制 Monkey 的执行范围。黑名单文档中每一行只能放一个包名
--pkg-whitelist-file < 白名单文件 > 限制 Monkey 只测试于指定白名单文档中记录的包。若没有使用这个参数,Monkey 会测试系统内所有的包。若使用了该参数,可通过在白名单文档内记录所有要测试的包名称,来限制 Monkey 的执行范围。白名单文档中每一行只能放一个包名
-f < 脚本文件 > 加载monkey脚本文件进行测试,比如 adb shell monkey -f sdcard/monkey.txt -v -v 500
# 1.3 Monkey事件
Monkey所执行的随机事件流中包含11大事件,分别是触摸事件、手势事件、二指缩放事件、轨迹事件、屏幕旋转事件、基本导航事件、主要导航事件、系统按键事件、启动Activity事件、键盘事件、其他类型事件。
1.3.1 触摸事件
触摸事件是指在屏幕某处按下并抬起的操作,可通过--pct-touch参数来配置其事件百分比。
1.3.2 手势事件
手势事件是指在屏幕某处的按下、随机移动、抬起的操作,即直线滑动操作。可通过--pct-motion参数来配置其事件百分比。
1.3.3 二指缩放事件
二指缩放事件是指在屏幕上的两处同时按下,并同时移动,最后同时抬起的操作,即智能机上的放大缩小手势操作。可通过--pct-pinchzoom参数来配置其事件百分比。
1.3.4 轨迹事件
轨迹事件是由一个或多个随机的移动组成的,有时会伴随着点击。可通过--pct- trackball参数来配置其事件百分比。
1.3.5 屏幕旋转事件
它其实是模拟的Android手机的横屏和竖屏切换。可通过--pct- rotation参数来配置其事件百分比。
1.3.6 基本导航事件
基本导航事件是指点击方向输入设备的上、下、左、右按键的操作,现在手机上很少有上、下、左、右按键,这种事件一般用得比较少。可通过--pct- nav参数来配置其事件百分比。
1.3.7 主要导航事件
主要导航事件是指点击“主要导航”按键的操作,这些按键通常会导致UI界面中的动作,如5-way键盘的中间键、回退按键、菜单按键。可通过--pct-majornav参数来配置其事件百分比。
1.3.8 系统按键事件
系统按键事件是指点击系统保留使用的按键的操作,如点击Home键、返回键、音量调节键等。可通过--pct-syskeys参数来配置其事件百分比。
1.3.9 启动Activity事件
启动Activity事件是指在手机上启动一个Activity的操作。在随机的时间间隔中,Monkey将执行一个startActivity()方法,作为最大限度上覆盖被测包中全部Activity的一种方法。可通过--pct-appswitch参数来配置其事件百分比。
1.3.10 键盘事件
键盘事件主要是一些与键盘相关的操作。比如点击输入框、键盘弹起、点击输入框以外区域、键盘收回等。可通过--pct-flip参数来配置其事件百分比。
1.3.11 其他类型事件
其他类型事件包括了除前面提到的10种事件外其他所有的事件,如按键、其他不常用的设备上的按钮等。可通过--pct-anyevent参数来配置其事件百分比。因为现在手机很少带字母按键或数字按键,所以这个事件一般使用得比较少。
# 1.4 Monkey环境搭建
Monkey是由adb命令来启动的,故只要配置好adb环境即可。
(1)下载并安装Android SDK和JDK。
(2)将Android SDK目录下的platform-tools和tools目录配置到系统环境变量Path中。
(3)打开cmd命令行窗口,输入“adb”,能显示adb帮助信息,则Monkey环境配置成功。
# 1.5 Monkey启动
Monkey启动方式很简单:先连接被测手机到PC上,然后打开CMD命令行窗口输入对应的adb命令行即可。
# 通过命令行启动Monkey有两种方式:
# 直接PC启动
adb shell monkey [options] <count>
# Shell端启动
adb shell
monkey [options] <count>
# 这两者的区别是,通过PC端启动,Monkey运行日志可以保存在PC上;通过Shell端启动,Monkey运行日志可以保存在手机里.
[注意]:Monkey启动后会不断地向被测对象发送随机事件流,直到事件执行完毕或者发送异常时才停止。在Monkey运行过程中,即便断开与PC的连接,Monkey依然可以在手机上继续运行。
停止Monkey的方法是:直接杀掉手机上的Monkey进程。
adb shell ps | grep monkey # 获取到com.android.commands.monkey的进程ID
adb shell kill [pid] # 通过kill命令杀死对应的Monkey进程
# 二. Monkey测试方法
# 2.1 Monkey测试实例
2.1.1 常规的稳定性测试
# 测试希望通过Monkey来模拟用户长时间的随机操作,检查被测应用是否会出现异常(应用崩溃或者无响应)。
adb shell monkey -p com.zhangyun.bravo --pct-touch 40 --pct-motion 25 --pct-appswitch 10 --pct-rotation 5 -s 12358 --throttle 400 --ignore-crashes --ignore-timeouts -v 500000
# 1) 使用-p参数来制定测试应用的包名(Package)
# 2) 使用--pct-xxx参数限制Monkey执行的事件类型和占比
# 触摸事件和手势事件是用户最常见的操作,所以通过--pct-touch和--pct-motion将这两个事件的占比调整到40%与25%;目标应用包含了多个Activity,为了能覆盖大部分的Activity,所以通过--pct-appswitch将Activity切换的事件占比调整到10%;被测应用之前在测试中出现过不少横竖屏之间切换的问题,这个场景也必须关注,因此通过--pct-rotation把横竖屏切换事件调整到10%
# 3) 使用-s参数来指定命令执行的seed值
# 4) 使用--throttle参数来控制Monkey每个操作之间的时间间隔
# 指定操作之间的时间间隔,一方面是希望能更接近用户的操作场景,正常用户操作都会有一定的时间间隔;另一方面也是不希望因为过于频繁的操作而导致系统崩溃,尤其是在比较低端的手机上执行测试时。因此通过--throttle设置Monkey每个操作固定延迟0.4秒。
# 5) 使用--ignore-crash和--ignore-timeouts参数使Monkey遇到意外时能继续执行
# 6) 使用-v指定log的详细级别,500000表示执行500000次伪随机事情
技巧:
查找应用包名的方法有很多,这里简单列举几个常用的方法:
(1) 通过pm命令查看
adb shell
pm list package
(2) 通过查看APK源码下的AndroidManifest.xml文件
(3) 通过aapt命令查看
(4) 通过adb logcat抓取当前Android机运行的App的包名。
2.1.2 自定义脚本的稳定性测试
Monkey支持执行用户自定义脚本的测试,用户只需要按照Monkey脚本的规范编写好脚本,存放到手机上,启动Monkey通过-f scriptfile参数调用脚本即可。
# 代码清单 Monkey自定义脚本的编写模板
# 头文件,控制Monkey发送消息的参数,固定写即可
# 脚本类型,一般不用更改
type = raw events
# 脚本执行次数,但是由于Monkey命令本身可以指定执行次数,所以这里的设置是不生效的
count = 10
# 命令执行速率,速率也可使通过Monkey命令设置,这里的设置是不生效的
speed = 1.0
# 以下为Monkey命令
start data>>
LaunchActivity(pag_name, cl_name)
DispatchPress(KEYCODE_HOME)
脚本命令:
- LaunchActivity(pkg_name, cl_name): 启动应用,第一个参数是包名,第二个是启动的activity名
- DispatchPointer(downtime,eventTime,action,x,y,xpressure,size,metastate,xPrecision,yPrecision,device,edgeFlags) :向指定位置发送单个手势,相当于我们把手指按在某个点上;这个方法参数有12个,但是我们主要关注owntime,eventTime,action,x,y这么几个参数,x,y表示按下的坐标,可以通过上一篇文章UI Automator获取,这在你想测试点击某个具体view是很有用的
- DispatchPress(keycode): 向系统发送一个固定的按键事件;例如home键,back键;参数是按键值 ,按键值可查看keycode
- UserWait:让脚本的执行暂停一段时间,做一个等待操作
- RotateScreen(rotationDegree, persist): 翻转屏幕,第一个参数是旋转角度,第二个是旋转后是否停在当前位置
- Tap(x, y) :单击事件,点击屏幕,参数是点击坐标
- Drag(xStart, yStart, xEnd, yEnd) :在屏幕上滑动,坐标是从哪一点滑到哪一点
- LongPress(): 长按2s
- ProfileWait(): 等待5s
- PressAndHold(x, y, pressDuration) :模拟长按
- PinchZoom(x1Start, y1Start, x1End, y1End, x2Start, y2Start, x2End, y2End, stepCount): 模拟缩放
- DispatchString(input): 输入字符串
- RunCmd(cmd) :执行shell命令,比如截图 screencap -p /data/local/tmp/tmp.png
- DispatchFlip(true/false) :打开或者关闭软键盘
- UserWait(sleepTime) :睡眠指定时间
- DeviceWakeUp() :唤醒屏幕
技巧:
Monkey脚本只能通过坐标的方式来定位点击和移动事件的屏幕位置,这里就需要提前获取坐标信息。获取坐标信息的方法很多,最简单的方法就是打开手机中的开发人员选项,打开“显示指针位置”。随后,在屏幕上的每次操作,在导航栏上都会显示坐标信息。
# 这里要测试的是应用宝App,测试的操作是打开应用宝,点击输入框,输入“yyb”,点击搜索。搜索完成后,点击返回键返回应用宝首页。
# 首先,将在本地编写的测试脚本命名为monkey.script,脚本如下所示
# 启动测试
type = user
count = 49
speed = 1.0
# 启动应用宝
LaunchActivity(com.tencent.android.qqdownloader, com.temcent.assistant.activity.SplashActivity)
UserWaid(2000)
# 点击搜索框
Tap(463, 150, 1000)
UserWait(2000)
# 输入字母“yyb”
DispatchString(yyb)
UserWait(2000)
# 点击搜索
Tap(960, 150, 1000)
UserWait(2000)
# 点击返回键返回首页
DispatchPress(KEYCODE_BACK)
# 其次,将文件push到手机或模拟器的sdcard中
adb push monkey.script /sdcard/
# 最后,执行脚本
adb shell monkey -f /sdcard/monkey.script -v 1
技巧:
查找应用Activity名称的方法有很多,这里简单列举几个常用的方法:
(1) 通过包名查看Activity名称
adb shell dumpsys package [包名]
(2) 使用aapt
2.1.3 结合辅助命令,获取更多信息
测试除了想知道执行过程是否有异常,还需要能获取执行过程中的一些详细信息或性能数据,比如想知道Monkey执行过程中是否存在内存泄漏,需要获取内存信息。下面列举了几种Monkey测试中常用的辅助命令,使用方法也非常简单,只要在执行Monkey的同时,另起一个CMD命令行窗口输入对应命令执行即可。
# 1. 获取logcat日志信息:
adb shell logcat -v time>log.txt
# 2. 获取内存信息:
adb shell dumpsys meminfo <进程名>
# 3. 获取CPU消耗信息:
adb shell top -n 1 | find <进程名>
# 4. 获取电量信息:
adb shell dumpsys battery
# 5. 获取GPU信息:
adb shell dumpsys gfxinfo <进程名>
# 6. 获取流量信息:
adb shell cat /proc/uid_stat/<被测应用的uid>/tcp_rcv
技巧:
如何获取被测应用的UID
步骤1:查看被测应用的进程ID(PID)
adb shell ps | grep <被测应用包名>
步骤2:查看被测应用的用户ID(UID)
adb shell cat /proc/<进程id>/status
2.1.4 Monkey测试策略制定思路
前面介绍了几种常见的Monkey测试方法,但在实际项目中,选择哪种Monkey测试策略,则需要根据实际项目的情况来做判断。主要是看测试目的及被测应用自身的特点。假如我们想测试浏览器的双指缩放功能是否有异常,那就需要选择--pct-pinchzoom参数,调大双指缩放事件的占比进行Monkey测试;假如我们想验证ROM的横竖屏切换功能是否正常,那就需要选择--pct-rotation参数,调大横竖屏切换事件的占比进行Monkey测试;假如我们想验证重复某种特定操作时,应用是否会存在异常,那可以选择-f参数,自定义Monkey脚本进行验证;假如我们想验证长时间操作时应用是否会存在内存泄漏,那就需要结合-hprof参数和dumpsysmeminfo <进程名>进行Monkey测试。
总之,Monkey测试策略是需要依据测试目的和被测程序的特点来制定的。
# 2.2 Monkey日志分析
2.2.1 Monkey日志保存方法
# 1. 保存再PC中,代码如下:
abd shell monkey [option] <count> > d:\monkey.txt
# 2. 保存在手机中,代码如下
adb shell
monkey [option] <count> > /mnt/sdcard/monkey.txt
# 3. 标注流与错误流分开保存,代码如下:
adb shell
monkey [option] <count> 1> /sdcard/monkey.txt 2>/sdcard/error.txt
2.2.2 Monkey日志内容解析
Monkey运行时输出的日志一般包含四类信息,分别是测试命令信息、伪随机事件流信息、异常信息、Monkey执行结果信息。要统计Monkey日志中错误出现的次数也非常简单,只要搜索关键字“ANR”和“CRASH”出现的次数即可。