Monkey自动化测试

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信息

如下图:
Monkey自动化测试_第1张图片
image.png

可直接根据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的脚本模式~

你可能感兴趣的:(Monkey自动化测试)