Monkey概念介绍
Monkey是猴子的意思。Monkey测试,就像一只猴子,在电脑面前,乱敲键盘在测试。猴子什么都不懂,只知道乱敲。
Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中。它向系统发送伪随机的用户事件流(如按键输入、触摸屏输入、手势输入等),实现对正在开发的应用程序进行压力测试。
Monkey命令
Monkey基本语法
adb shell monkey [options]
如果不指定options,Monkey将以无反馈模式启动,并把事件任意发送到安装在目标环境中的全部包。
Monkey常用命令
1,-help 列出简单使用指南。
如:adb shell monkey -help
2,-v 每增加一个-v都将增加反馈信息的详细级别。
如:adb shell monkey -v -v -v 100
表示执行100个伪随机用户事件流,并提供了测试中所有相关Activity信息。
Level 0(默认),除了启动、测试完成和最终结果外只提供较少的信息。
Level 1,提供了较为详细的测试信息,如逐个发送到Activity的事件信息。
Level 2,提供了更多的设置信息,如测试中选中或未选中的Activity信息。
3,-s < seed> 伪随机数生成器的种子值。如果你用相同的种子值重新运行Monkey,它将生成相同的事件序列。
如:adb shell monkey -s 1123
表示重现种子值为1123的事件序列。
4,-throttle < milliseconds> 在事件之间插入固定延迟。通过这个选项可以减缓Monkey的执行速度。如果不指定该选项,Monkey将不会被延迟,事件将尽可能快地被产成。
如:adb shell monkey -throttle 300 -v 100
表示执行100个伪随机用户事件流,事件间隔为300毫秒。
注:一般设置为300毫秒,原因是实际用户操作的最快300毫秒左右一个动作事件。
5,-pct-touch< percent> 表示调整触摸事件的百分比(触摸事件是屏幕上单个位置的down-up事件)。
如:adb shell monkey -pct-touch 67 -v 10
表示执行10个伪随机用户事件流,并调整其中触摸事件的百分比为67%。
注:此参数设置要适应当前被测应用程序的操作,比如一个应用80%的操作都是触摸,那就可以将此参数的百分比设置成相应较高的百分比。
6,-pct-motion < percent> 表示调整动作事件的百分比(动作事件由屏幕上某处的一个down事件、一系列的伪随机事件和一个up事件组成)。
如:adb shell monkey -pct-motion 67 -v 10
表示执行10个伪随机用户事件流,并调整其中动作事件的百分比为67%。
注:这里的移动是直线滑动,下面的trackball移动包含曲线移动。
7,-pct-trackball < percent> 表示调整轨迹球事件的百分比(轨迹球事件由一个或多个随机移动组成,有时还伴随有点击)。
如:adb shell monkey -pct-trackball 67 -v 10
表示执行10个伪随机用户事件流,并调整其中轨迹球事件的百分比为67%。
8,-p < allowed-package-name> 表示如果用此参数指定了一个或几个包,Monkey将只允许系统启动这些包里的Activity。如果你的应用程序还需要访问其它包里的Activity(如选择取一个联系人),那些包也需要在此同时指定。如果不指定任何包,Monkey将允许系统启动全部包里的Activity。要指定多个包,需要使用多个 -p选项,每个-p选项只能用于一个包。
如:adb shell monkey -p com.jzf.simple1 -p com.jzf.simple2 100
表示对包“com.jzf.simple1”和“com.jzf.simple2”执行100个伪随机用户事件流。
9,-c < main-category> 表示如果用此参数指定了一个或几个类别,Monkey将只允许系统启动这些指定类别中列出的Activity。如果不指定任何类别,Monkey将选 择下列类别中列出的Activity: Intent.CATEGORY_LAUNCHER或Intent.CATEGORY_MONKEY。要指定多个类别,需要使用多个-c选项,每个-c选 项只能用于一个类别。
10,-ignore-crashes 表示当应用程序崩溃或遇到任何类型的未处理的异常时,Monkey将停止。如果指定此选项,则Monkey将继续向系统发送事件,直到计数完成。
11,-ignore-timeouts 表示当应用程序遇到任何类型的超时错误(如“应用程序无响应”对话框)时,Monkey将停止。如果指定此选项,则Monkey将继续向系统发送事件,直到计数完成。
12,-ignore-security-exceptions 表示当应用程序遇到任何类型的权限错误时,Monkey将停止,例如,如果它尝试启动需要某些权限的活动。如果指定此选项,则Monkey将继续向系统发送事件,直到计数完成。
13,-kill-process-after-error 当Monkey由于一个错误而停止时,出错的应用程序将继续处于运行状态。当设置了此选项时,将会通知系统停止发生错误的进程。注意,正常的(成功的)结束,并没有停止启动的进程,设备只是在结束事件之后,简单地保持在最后的状态。
14,-monitor-native-crashes 表示Android系统原生代码中的监视和报告崩溃。如果设置了-kill-process-after-error,系统将停止。
15,-wait-dbg 表示停止执行中的Monkey,直到有调试器和它相连接。
16,adb shell -p com.jzf.simple -v -v -v 100 > monkey.txt
表示日志保存在系统目录的monkey.txt文件下
17,adb devices 查看设备是否连接成功,如果有手机串号说明连接成功。
18,adb shell pm list packages
表示查看手机内所有的包名。
Monkey日志分析
在执行随机事件流之后,终端会显示一组日志信息。比如你执行以下代码:
adb shell monkey -p your.app.name -v -v -v 500
表示对你的APP执行500个伪随机事件流并将反馈信息级别设置最高。
由于篇幅原因,这里简要列出一些日志进行说明。(//注:这里是事件说明)
jzf:~ jinzifu$ adb shell monkey -p com.zjrb.sjzsw -v -v -v 2
:Monkey: seed=1509666218694 count=2 //注:monkey执行的seed值和随机事件次数
:AllowPackage: com.zjrb.sjzsw //注:可以执行的包名
:IncludeCategory: android.intent.category.LAUNCHER
:IncludeCategory: android.intent.category.MONKEY //注:默认执行的activity的category类别
...
// Seeded: 1509666218694
// Event percentages: //注:分配事件的百分比,事件号对应如下
// 0: 15.0% //注:触摸事件百分比,即参数--pct-touch
// 1: 10.0% //注:手势事件百分比,即参数--pct-motion
// 2: 2.0% //注:缩放事件百分比,即参数--pct-pinchzoom
// 3: 15.0% //注:轨迹球事件百分比,即参数--pct-trackball
// 4: -0.0% //注:屏幕旋转事件百分比,即参数--pct-rotation
// 5: -0.0% //注:基本导航事件百分比,即参数--pct-nav
// 6: 25.0% //注:主要导航事件百分比,即参数--pct-majornav
// 7: 15.0% //注:系统事件百分比,即参数--pct-syskeys
// 8: 2.0% //注:Activity启动事件百分比,即参数--pct-appswitch
// 9: 2.0% //注:键盘翻转事件百分比,即参数--pct-flip
// 10: 1.0% //注:其他事件百分比,即参数--pct-anyevent
// 11: 13.0% //注:?
...
:Sending Touch (ACTION_DOWN): 0:(968.0,1004.0) //注:触摸事件
...
:Sending Key (ACTION_DOWN): 19 // KEYCODE_DPAD_UP //注:导航事件(上下左右)
:Sending Key (ACTION_UP): 19 // KEYCODE_DPAD_UP
...
:Sending Key (ACTION_DOWN): 66 // KEYCODE_ENTER //注:其他事件
:Sending Key (ACTION_UP): 66 // KEYCODE_ENTER
...
:Sending Trackball (ACTION_MOVE): 0:(2.0,2.0) //注:轨迹球事件
...
Sending Flip keyboardOpen=false //注:键盘事件(隐藏显示键盘)
...
注:Monkey的事件种类一般是11种,不同的Android SDK中的Event percentages种类和顺序也不同哦。
CRASH
在Monkey测试过程中可能会出现程序崩溃(CRASH)和程序无响应的情况(ANR),要将测试的log信息获取到,从而解决bug。这里仅以CRASH为例说明。
CRASH即崩溃信息,程序在运行中非正常退出。 不设置忽略crashes,在测试过程中出现CRASH,会中断测试,并显示CRASH信息和seed信息
可直接根据log日志定位bug并修复,也可根据seed值来完成bug的复现。
如:adb shell monkey -p com.feicuiedu.monkeytestdemo -s 1476474162566 -v 100
Monkey的原理
"adb shell monkey"运行机理
实际上是在执行手机中的/sysytem/bin/monkey的脚本文件,其内容如下:
# Script to start "monkey" on the device, which has a very rudimentary
# shell.
#
base=/system
export CLASSPATH=$base/framework/monkey.jar
trap "" HUP
exec app_process $base/bin com.android.commands.monkey.Monkey $*
从系统源码看,其内部是通过/system/bin/app_process来运行/system/framework/monkey.jar。
这里需要注意,JVM中的jar文件是一对class文件的zip包。而在Android中,可执行文件是dex,所以Android里面的jar本质上里面也是dex,直接把eclipse导出的jar包放进去是无法执行的。
其中,app_process会新建一个native进程,初始化虚拟机,从CLASSPATH找到我们定义的Main Class,并把参数传给它。app_process部分启动源码如下:
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
}
adb这里是runtime执行com.android.internal.os.RuntimeInit来启动,位置在:/system/framework/下面。该目录下有很多系统的包,其中有一个/system/framework/monkey.jar为monkey的所在包。
Monkey事件注入机制
Monkey注入系统事件是通过framework层的hidenApi(如:activemanager,inputmanager,windowmanager)获取系统服务。如下:
触摸事件:包括屏幕以及物理键的触摸,滑动,点击事件。
Monkey通过InputManager.getInstance().injectInputEvent(keyEvent, int);
构造对应的事件,然后调用该接口执行事件。
Activity事件:是指我们调用Android系统组件的事件。
Monkey通过IActivityManager实例来获取activity的系统服务,从而启动某个activity。
IActivityManager am = ActivityManagerNative.getDefault();
am.startActivity();
Window事件:是指操作Window的事件,例如转屏。
Monkey通过获取IWindowManager实例开启系统窗口服务,并执行窗口事件。
IWindowManager wm = null;
wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
wm..thawRotation();//窗口转屏
Monkey的组织结构
Monkey的核心类是Monkey.java,MonkeyEventSource.java,MonkeyEvent.java。
类名 | 描述 |
---|---|
Monkey | 程序的入口,同时也是调度中心,根据参数选择合适的MonkeyEventSource,并适时触发MonkeyEvent。 |
MonkeyEventSource | MonkeyEvent的工厂,是一个接口。它有各种实现,例如随机生成MonkeyEvent,根据配置文件生成MonkeyEvent,根据网络数据生成MonkeyEvent等等。 |
MonkeyEvent | 各种事件的具体实现,是一个抽象类,不同事件有不同实现。在Monkey中各种活动都是事件,除了基本的触摸事件,Activity事件外,事件之间的停顿也是通过一个MonkeyThrottleEvent来实现。这样概念的扩展,将各种活动一视同仁的对待,使设计变得简单。 |
Monkey中有11种事件,这些事件在MonkeyEventSource中对事件之间的比例进行设置。Monkey事件根据类型比例生成事件队列,循环查找事件。
在MonkeyEventSource中,对于事件来源主要有脚本模式、网络模式(monkeyRunner)和默认模式(随机事件)。
因此,如果我们需要扩展Monkey的功能,只需要增加自己实现的MonkeyEventSource和MonkeyEvent即可。
后续我们一起研究下Monkey的脚本模式~