1、简介
Monkey是一个程序,运行在您的模拟器或设备上,并生成伪随机的用户事件流,如点击,触摸或手势,以及一些系统级事件。可以使用Monkey以随机重复的方式来对应用程序进行一些稳定性、健壮性方面的测试。
官方文档:http://www.android-doc.com/tools/help/monkey.html
2、Monkey路径
Monkey程序是Android系统自带的,其启动脚本是位于Android系统的/system/bin目录的Monkey文件,其jar包是位于Android系统的/system/framework目录的Monkey.jar文件。用户主要是通过adb命令来启动Monkey的,Monkey在运行时,会根据命令行参数的配置,生成伪随机的事件流,并在Android设备上执行对应的测试事件。同时,Monkey还会对测试系统进行监测,当出现以下三种情况时会进行特殊处理:
- 如限定了Monkey运行在特定包上,当监测到试图转到其他包的操作,将对其进行阻止。
- 如应用程序崩溃或接收到任何失控异常,Monkey将记录对应的错误日志,并根据命令行参数判断是停止运行还是继续运行。
- 如果应用程序发生了程序无响应(application not responding)的错误,Monkey将记录对应的错误日志,并根据命令行参数判断是停止运行还是继续运行。
按照选定的不同级别的反馈信息,在Monkey中还可以看到其执行过程报告和生成的事件。
3、强制关闭Monkey
步骤:
-
adb shell ps
查看全部在运行的进程 - 查找出
com.android.commands.monkey
进程PID -
adb shell kill PID
强制杀掉monkey进程
4、Monkey命令解析
adb shell monkey [options]
- [options]:指monkey可传入的参数,是可选项(如果不指定options,Monkey将以无反馈模式启动,并把事件任意发送到安装在目标环境中的全部包)
:指随机发送事件数。如:输入100就是执行100个伪随机事件,为必选项。
5、Monkey事件解析
5.1、触摸事件:--pct-touch
触摸事件是指在屏幕某处按下并抬起的操作,可通过--pct-touch参数来配置其事件百分比。从Monkey执行该事件对外输出的日志可以看到。 该事件由一组Touch(ACTION_DOWN)和Touch(ACTION_UP)事件组成,在手机上看到实际操作类似于点击。
5.2、手势事件:--pct-motion
手势事件是指在屏幕某处的按下、随机移动、抬起的操作,即直线滑动操作。可通过--pct-motion参数来配置其事件百分比。该事件是由一个ACTION_DOWN事件、一系列ACTION_MOVE事件和一个ACTION_UP事件组成的,在手机上看到的实际操作是一个没有拐弯的直线滑动操作。
5.3、二指缩放事件:--pct-pinchzoom
二指缩放事件是指在屏幕上的两处同时按下,并同时移动,最后同时抬起的操作,即智能机上的放大缩小手势操作。可通过--pct-pinchzoom参数来配置其事件百分比。从Monkey执行该事件对外输出的日志可以看到:该事件起始是一个ACTION_DOWN事件和一个ACTION_POINTER_DOWN事件,即模拟两个手指同时点下;中间是一系列的ACTION_MOVE事件,即两个手指同时在屏幕上直线滑动;结束是由一个ACTION_POINTER_UP事件和一个ACTION_UP事件组成的,即两个手指同时放开。
5.4、轨迹事件:--pct-trackball
轨迹事件是由一个或多个随机的移动组成的,有时会伴随着点击。很早之前的Android手机带有轨迹球,这个事件就是模拟的轨迹球的操作。现在的手机几乎都没有轨迹球,但轨迹球事件中包含曲线滑动操作,如果被测程序需要曲线滑动时可以选用此参数。可通过--pct-trackball参数来配置其事件百分比。从Monkey执行该事件对外输出的日志可以看到:该事件是由一系列的Trackball(ACTION_MOVE)事件组成的,观察手机上的操作,即为一系列的曲线滑动操作。
5.5、屏幕旋转事件:--pct-rotation
屏幕旋转事件是一个隐藏事件,在Android官方文档中并没有记录这个事件。它其实是模拟的Android手机的横屏和竖屏切换。可通过--pct-rotation参数来配置其事件百分比。从Monkey执行该事件对外输出的日志可以看到: [代码] 该事件由一个rotation事件组成,其中degree表示的是旋转方向,顺时针旋转,0表示旋转90度的方向,1表示旋转180度的方向,2表示旋转270度的方向,3表示旋转360度的方向。在执行过程中,可以看到手机屏幕在横竖屏之间不断地切换。
5.6、基本导航事件:--pct-nav
基本导航事件是指点击方向输入设备的上、下、左、右按键的操作,现在手机上很少有上、下、左、右按键,这种事件一般用得比较少。可通过--pct-nav参数来配置其事件百分比。从Monkey执行该事件对外输出的日志可以看到:该事件是由一个Key(ACTION_DOWN)和一个Key(ACTION_UP)组成的,点击的就是上、下、左、右四个方向按键。
5.7、主要导航事件:--pct-majornav
主要导航事件是指点击“主要导航”按键的操作,这些按键通常会导致UI界面中的动作,如键盘的中间键、回退按键、菜单按键。可通过--pct-majornav参数来配置其事件百分比。从Monkey执行该事件对外输出的日志可以看到: [代码] 该事件是由一个Key(ACTION_DOWN)和一个Key(ACTION_UP)组成的,点击的按键就是中间键和菜单键。
5.8、系统按键事件:--pct-syskeys
系统按键事件是指点击系统保留使用的按键的操作,如点击Home键、返回键、音量调节键等。可通过--pct-syskeys参数来配置其事件百分比。从Monkey执行该事件对外输出的日志可以看到: [代码] 该事件是由一个Key(ACTION_DOWN)和一个Key(ACTION_UP)组成的,点击的就是上面说到的几个系统按键。
5.9、启动Activity事件:--pct-appswitch
启动Activity事件是指在手机上启动一个Activity的操作。在随机的时间间隔中,Monkey将执行一个startActivity()方法,作为最大限度上覆盖被测包中全部Activity的一种方法。可通过--pct-appswitch参数来配置其事件百分比。从Monkey执行该事件对外输出的日志可以看到: [代码] 该事件是由一个Switch操作组成的,从手机上看,上面的操作实际是打开了com.android.settings这个应用的一个com.android.settings.Settings的Activity界面。
5.10、键盘事件:--pct-flip
键盘事件主要是一些与键盘相关的操作。比如点击输入框、键盘弹起、点击输入框以外区域、键盘收回等。可通过--pct-flip参数来配置其事件百分比。从Monkey执行该事件对外输出的日志可以看到: [代码] 如日志所示,这里主要是键盘的打开和关闭操作。
5.11、其他类型事件:--pct-anyevent
其他类型事件包括了除前面提到的10种事件外其他所有的事件,如按键、其他不常用的设备上的按钮等。可通过--pct-anyevent参数来配置其事件百分比。从Monkey执行该事件对外输出的日志可以看到: [代码] 该事件是由一个Key(ACTION_DOWN)和一个Key(ACTION_UP)组成的,点击的按键就是其他的一些系统按键,如字母按键、数字按键等。因为现在手机很少带字母按键或数字按键,所以这个事件一般使用得比较少。
6、Monkey参数解析
6.1、常规类参数
6.1.1、帮助类参数:monkey -h
6.1.2、日志级别:monkey -v
-v:打印出日志信息,每个-v将增加反馈信息的级别。-v越多日志信息越详细,不过目前最多支持3个-v,即:
日志级别Leve 0:adb shell monkey -p com.tencent.mobileqq -v 100
日志级别Leve 1:adb shell monkey -p com.tencent.mobileqq -v -v 100
日志级别Leve 2:adb shell monkey -p com.tencent.mobileqq -v -v -v 100
6.2、事件类参数
事件类参数的作用是对随机事件进行调控,从而使其遵照设定运行,如设置各种事件的百分比、设置事件生成所使用的种子值等。频率参数主要限制事件执行的时间间隔。
6.2.1、执行指定脚本: -f <路径>
示例:
adb shell monkey -f "F:\Game\jkk.txt"
6.2.2、伪随机数生成种子值: -s
使用 -s命令可以重复执行之前的伪随机操作。本身每次执行伪随机事件操作也会默认生成一个seed值。
示例:
adb shell monkey -s 22632 1000 # :22632,:1000
6.2.3、设置间隔: --throttle
在每一个指令之间加上固定的间隔时间,可以用--throttle(注意,前面是--)命令。表示事件之间的固定延迟(即执行每一个指令间隔的时间),若不接该选项,monkey将不会延迟。--throttle:后面接时间,单位为ms(
示例:发送100次随机事件,每次事件间隔为3s
adb shell monkey -p com.tencent.mm --throttle 3000 100
6.2.4、调整触屏事件百分比: --pct-touch{+事件类别百分比}
触屏事件是一个有手指按下、抬起事件的手势。
注意:触摸事件不单单是按键,它泛指发生在某一位置的一个down-up事件。
示例:发送100次随机事件,每次事件间隔为3s,其中设定触屏事件百分比为50%
adb shell monkey --pct-touch 50 -p com.tencent.mm --throttle 3000 100
6.2.5、调整滑动事件百分比:--pct-motion{+事件类别百分比}
滑动事件是一个先在某一个位置手指按下,滑动一段距离后再抬起手指的手势。
示例:发送100次随机事件,每次事件间隔为3s,其中设定滑动事件百分比为50%
6.2.6、调整应用启动事件的百分比:--pct-appswitch{+事件类别百分比}
--pct-appswitch:后面接应用启动事件百分比。
应用启动事件(即activity launches)俗称打开应用,通过调用startActivity()方法最大限度地开启该package下的所有应用。
adb shell monkey -p com.tencent.mm --pct-appswitch 10 1000
6.2.7、调整屏幕旋转事件百分比:--pct-rotation{+事件类别百分比}
--pct-rotation 后面接屏幕旋转事件的比例值。
adb shell monkey -p com.tencent.mm --pct-rotation 30 1000
6.2.8、调整轨迹事件百分比:--pct-trackball{+事件类别百分比}
调整轨迹事件的百分比(轨迹事件由一个或几个随机的移动组成,有时还伴随有点击)
adb shell monkey -p com.tencent.mm --pct-trackball 30 1000
6.2.9、调整“基本”导航事件百分比:--pct-nav {+事件类别百分比}
调整“基本”导航事件的百分比(导航事件由来自方向输入设备的up/down/left/right组成)
adb shell monkey -p com.tencent.mm --pct-nav 40 1000
6.2.10、调整“主要”导航事件的百分比:--pct-majornav {+事件类别百分比}
调整“主要”导航事件的百分比(这些导航事件通常引发图形界面中的动作,如:中间按键、回退按键、菜单按键)。
adb shell monkey -p com.tencent.mm --pct-majornav 50 1000
6.2.11、调整其他类型事件的百分比:--pct-anyevent{+事件类别百分比}
设定其他类型事件的百分比,如普通的按键消息、不常用的设备按钮事件等。
adb shell monkey --pct-anyevent 50 -p com.tencent.mm --throttle 3000 100
6.3、约束类参数
6.3.1、包约束:-p
-p:后面接一个或多个包名(
adb shell monkey -p
# 指定一个包:
adb shell monkey -p com.tencent.mm 100
# 指定多个包:
adb shell monkey -p com.tencent.mm -p com.tencent.mobileqq 100
# 不指定包:
adb shell monkey 100
6.3.2、Activity类约束:-c
将monkey限制在一个或几个类别中,使用如下命令:
示例:运行Intent.CATEGORY_LAUNCHER类别的Activity并发送1000个随机事件。
adb shell monkey -c Intent.CATEGORY_LAUNCHER 1000
6.4、调试类参数
6.4.1、应用程序崩溃后继续发送事件:--ignore-crashes
想让monkey在应用程序崩溃后继续发送事件,则需要用到--ignore-crashes命令,在设置此选项后,当应用程序崩溃或发生失控异常时,monkey将继续运行直到计数完成。如果不设置此选项,monkey遇到上述崩溃或异常将停止运行。
adb shell monkey --ignore-crashes
6.4.2、超时错误继续发送事件:--ignore-timeouts
monkey在任何超时错误发生后继续发送事件,则需要用到--ignore-timeouts命令。--ignore-timeouts:在设置此选项后,当应用程序发生任何超时错误(如ANR,即Application Not Responding)时,monkey将继续运行直到计数完成。如果不设置此选项,monkey遇到此类超时对话框将停止运行。
adb shell monkey --ignore-timeouts
6.4.3、应用程序权限错误发生后继续发送事件:--ignore-security-exceptions
monkey在应用程序权限错误发生后继续发送事件,则需要用到--ignore-security-exceptions命令。--ignore-security-exceptions:在设置此选项后,当应用程序发生任何权限错误(如启动一个需要某些权限的Activity)时,monkey将继续运行直到计数完成。如果不设置此选项,monkey遇到此类权限错误将停止运行。
adb shell monkey --ignore-security-exceptions
6.4.4、在应用程序出错后通知系统停止发生错误的进程:--kill-process-after-error
通常情况下,当Monkey由于一个错误而停止时,出错的应用程序将继续处于运行状态,当设置了此选项时,将会通知系统停止发生错误的进程。
注意:当Monkey正常执行完毕后,它不会关闭所启动的应用,设备依然保留其最后接收到的消息状态,所以建立在执行命令以后为保持应用的初始状态,需手动或者脚本程序就已打开的应用进行关闭。
adb shell monkey --kill-process-after-error
6.4.5、进入到一个测试Activity,不会再进一步生成事件:--dbg-no-events
若指定了该参数,Monkey将会执行初始启动,进入到一个测试Activity,不会再进一步生成事件。为了得到最佳结果,就它与“-v”、“-p”、“--throttle”等参数一起使用,并让Monkey运行30s或更长时间,从而能够让我们可以观测到应用程序所调用的包与包之间的切换过程。
adb shell monkey --dbg-no-events
6.4.6、生成性能分析报告:--hprof
若指定了该参数,Monkey会在发送事件序列的前、后,生成性能分析报告,通常会在“data/misc”目录下生成一个5MB左右大小的文件。
adb shell monkey --hprof
6.4.7、监视由Android C/C++代码引起的崩溃:--monitor-native-crashes
监视由Android C/C++代码引起的崩溃,若同时指定了--kill-process-after-error参数,则整个系统将会关机。
adb shell monkey --monitor-native-crashes
6.4.8、 启动Monkey后,中断其运行,等待调速器和它相连接:--wait-dbg
adb shell monkey --wait-dbg
7、monkey日志管理
7.1、日志保存方法
7.1.1、将日志保存在计算机上
adb shell monkey -v -v 100 >d:\monkeylog.txt
7.1.2、将日志保存在手机上
adb shell monkey -v 100 >/sdcard/monkeylog.log
7.1.3、标准流和错误流分开保存
adb shell monkey -v 100 1>d:\monkey.log 2>d:\error.log
# 标准流:1>d:\monkey.log
# 错误流:2>d:\error.log
执行以上命令,Monkey的运行日志和异常日志将被分开保存。此时Monkey的运行日志将被保存在monkey.txt文件中,而异常日志将被保存在D盘下的error.txt中。
7.2、日志内容分析
(1)、初步分析
一般的测试结果分析:
ANR问题:在日志中搜索“ANR”
崩溃问题:在日志中搜索“Exception” Force Close
Monkey测试出现错误后,一般的查错步骤为以下几步:
找到是Monkey里面的哪个地方出错。
查看Monkey里面出错前的一些事件动作,并手动执行该动作。
若以上步骤还不能找出,可以使用之前执行的Monkey命令再执行一遍,注意seed值要一样--复现。
(2)、详细分析
8、monkey相关命令介绍(实现自动化脚本命令)
8.1、DispatchPointer命令
命令说明:该命令用于向一个坐标点发送手势消息。
命令原型:
DispatchPointer(long downTime, long eventTime, int action, float x, float y, float pressure, float size, int metaState, float xPrecision, float yPrecision, int device, int edgeFlags);
参数介绍:通常只需要设置前5个关键参数,其他参数可以设置为0
- downTime:表示键最初被按下的时间,该值只要是一个合法的长整数类型(long)就可以。
- eventTime:表示事件发生的时间,该值只要是一个合法的的长整数类型(long)就可以。
- action:表示发送消息的类型,0:按下;1:抬起;2:移动
- x:表示x轴坐标
- y:表示y轴坐标
- pressure:表示当前事件的压力,压力的范围一般从0(没有压力)到1(正常压力)。
- size:表示触摸的近似值,范围0-1。
- metaState:表示当前按下的meta键的标识,meta键指的是ALT、Shift、CAPS_LOCK.
- xPrecision:表示x坐标精确值。
- yPrecision:表示y坐标精确值。
- device:表示事件来源。
- edgeFlags:表示边缘指示,如果有的话,在该位置会触发位移事件。
8.2、DispatchTrackball命令
命令说明:该命令用于向一个坐标点发送跟踪球消息,它的使用方法和DispatchPointer命令完全相同。
8.3、DispatchKey命令
命令说明:该命令用于发送按键消息给指定的设备或者模拟器。
命令原型:
DispatchKey(long downTime, long eventTime, int action, int code**,* *int repeat, int metaState, int device, int scancode);
参数介绍:
- downTime:表示键最初被按下的时间,该值只要是一个合法的长整数类型(long)就可以。
- eventTime:表示事件发生的时间,该值只要是一个合法的的长整数类型(long)就可以。
- action:表示发送消息的类型,0:按下;1:抬起;2:移动
- code:表示按键的值
- repeat:表示按键的重复次数
8.4、DispatchFlip命令
命令说明:该命令用于打开或关闭软键盘
命令原型:
DispatchFlip(boolean keyboardOpen)
参数介绍:
- 当keyboardOpen为“true”时,表示打开软键盘;“false”时表示关闭软键盘
8.5、LaunchActivity命令
命令说明:该命令用于启用任意引用的一个活动界面
命令原型:
LaunchActivity(String pkg_name, String cl_name)
参数介绍:
- pkg_name:要启动的应用包名。
- cl_name:要启动的活动名称。
8.6、LaunchInstrumentation命令
命令说明:该命令用于一个仪表盘参数用例
命令原型:
LaunchInstrumentation(test_name, runner_name)
参数介绍:
- test_name:要运行的测试用例名。
- runner_name:运行测试用例的类名。
8.7、UserWait命令
命令说明:该命令用于让脚本中断一段时间
命令原型:
UserWait(long sleeptime)
参数介绍:
- sleeptime:单位为毫秒。
8.8、RunCmd命令
命令说明:该命令用于在设备上运行Shell命令。
命令原型:
RunCmd(cmd)
参数介绍:
- cmd:要执行的shell命令
8.9、Tap命令
命令说明:该命令用于模拟一次手指单击事件
命令原型:
Tap(x, y, tapDuration)
参数介绍:
x,y:坐标值
tapDuration:可选项,表示单击的持续时间
8.10、ProfileWait命令
命令说明:该命令用于等待5s
命令原型:
ProfileWait()
8.11、DeviceWakeUp命令
命令说明:该命令用于唤醒设备并解锁
命令原型:
DeviceWakeUp()
8.12、DispatchString命令
命令说明:该命令用于向Shell输入一个字符串
命令原型:
DispatchString(input)
参数介绍:
- input:要输入的字符串内容。
9、monkey如何执行脚本
- 编写脚本
- adb push上传入手机
- adb shell monkey -f /scard/monkey_demo 1运行脚本
- 示例:编写QQ登录脚本
# monkey脚本开头,固定格式
type= raw events # 表示脚本的类型
count = 1 # 说明执行次数
speed = 1.0 # 用于调整两次执行随机事件的发送频率
start data >> # 一个特殊的分隔符,相当于一个入口,说明脚本从下面开始就是真正的Monkey相关的事件序列执行语句。
# 启动QQ
LaunchActivity(com.tencent.mobileqq,com.tencent.mobileqq.activity.LoginActivity) UserWait(5000)
# 点击登录
DispatchPointer(0,0,0,262,1778,0,0,0,0,0,0,0)
DispatchPointer(0,0,1,262,1778,0,0,0,0,0,0,0)
UserWait(200)
#确定账号输入框,输入账号
DispatchPointer(0,0,0,264,391,0,0,0,0,0,0,0)
DispatchPointer(0,0,1,264,391,0,0,0,0,0,0,0)
UserWait(200)
DispatchPress(KEYCODE_7)
UserWait(300)
DispatchPress(KEYCODE_3)
UserWait(300)
DispatchPress(KEYCODE_4)
UserWait(300)
DispatchPress(KEYCODE_2)
UserWait(300)
DispatchPress(KEYCODE_0)
UserWait(300)
DispatchPress(KEYCODE_0)
UserWait(300)
DispatchPress(KEYCODE_8)
UserWait(300)
DispatchPress(KEYCODE_8)
UserWait(300)
DispatchPress(KEYCODE_0)
UserWait(300)
# 确定密码输入框,输入密码
DispatchPointer(0,0,0,208,500,0,0,0,0,0,0,0)
DispatchPointer(0,0,1,208,500,0,0,0,0,0,0,0)
UserWait(200)
DispatchPress(KEYCODE_A)
UserWait(300)
DispatchPress(KEYCODE_B)
UserWait(300)
DispatchPress(KEYCODE_C)
UserWait(300)
DispatchPress(KEYCODE_D)
UserWait(300)
DispatchPress(KEYCODE_E)
UserWait(300)
DispatchPress(KEYCODE_F)
UserWait(300)
DispatchPress(KEYCODE_1)
UserWait(300)
DispatchPress(KEYCODE_2)
UserWait(300)
DispatchPress(KEYCODE_3)
UserWait(300)
DispatchPress(KEYCODE_4)
UserWait(300)
DispatchPress(KEYCODE_5)
UserWait(300)
DispatchPress(KEYCODE_6)
UserWait(300)
# 点击登录
DispatchPointer(0,0,0,537,614,0,0,0,0,0,0,0)
DispatchPointer(0,0,1,537,614,0,0,0,0,0,0,0)
UserWait(200)