APP性能测试之Monkey

交互设计

  1. 什么是Monkey?

  Monkey是Android中的一个命令行工具,可以运行在模拟器里或实际设备中。

  它向系统发送伪随机的用户事件流(如按键输入、触摸屏输入、手势输入等),实现对正在开发的应用程序进行压力测试。

  Monkey测试通俗些的理解:可以认为Monkey这个工具就是一个猴子,它在App中乱按、乱摸、乱滚、乱跳。

  通过这个工具可以模拟用户触摸屏幕、滑动轨迹球、按键等操作来对模拟器或者手机设备上的软件进行压力测试,

  检测该软件的稳定性、健壮性。

  2.Monkey测试环境构建:

  a、pc端下载adb命令包,并配置环境变量,path加上adb的目录路径 ,环境配置好后-->验证命令为: adb version

  b、 jdk环境变量配置好-->验证命令为:java -version

  c、手机已经打开开发者模式以及USB调试状态

  d、把手机锁屏设置为从不

  3.Monkey命令执行分解:

  首先我们清楚:Monkey程序由Android系统自带,使用Java语言写成,在Android文件系统中的存放路径是:/system/framework/monkey.jar

  而我们看到的Monkey.jar程序是由一个名为“monkey”的Shell脚本来启动执行

  这个shell脚本在Android文件系统中的存放路径是:/system/bin/monkey;

  如下截图所示:

  # Script to start "monkey" on the device, which has a very rudimentary

  # shell.

  #上面的备注是说明这个脚本是一个比较简单的用来启动设备上的Monkey脚本

  base=/system

  #声明base变量 ,export是用来设置环境变量的,变量名为CLASSPATH,也就是设置#monkey的CLASSPATH环境变量指向monkey.jar

  export CLASSPATH=$base/framework/monkey.jar

  trap "" HUP

  #trap是一个shell内建命令,它用来在脚本中指定信号如何处理。这里的 trap "" HUP 表明忽略SIGHUP信号,即网络断开时也不能使脚本退出。

  exec app_process $base/bin com.android.commands.monkey.Monkey $*

  最后一行代表的是执行:

  总的就是:通过app_process指定monkey的入口和传进来的所有参数启动上面CLASSPATH设定的monkey.jar

  通过以上的app_process指定的monkey入口,我们可以知道我们的入口函数main是在com.android.commands.Monkey这个类里面

  Exec可以理解为执行

  app_process:Android上app_process启动java进程

  $* :传递给脚本或函数的所有参数

  4.monkey命令的执行方式:

  运行Monkey的方式有四种:

  a、pc机上 adb shell monkey +参数

  如:adb shell monkey -p com.autochina.p2p -v 100 > e:\p2p.log //这种方式比较常使用

  b、 pc机输入adb shell进入到手机的安卓设备后再monkey+参数

  c、手机设备上安装一个模拟器手机执行monkey+参数(手机模拟器可以通过百度搜索或360手机助手搜android terminal,安装即可,可以在模拟器的命令行中输入mokey +参数)

  d、脚本方式

  Android 的monkey test 工具提供了 -f scriptfile 参数,可以指定 test 脚本。在 monkey 的源码 MonkeySourceScript.java 中有一小段注释,里面给了一个不到 10 行例子:

  monkey中提供的函数如下:

  15、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) 16、DispatchTrackball(long downTime, long eventTime, int action, float x, float y, float pressure, float size, int metaState, float xPrecision, float yPrecision, int device, int edgeFlags) 17、DispatchKey(long downTime, long eventTime, int action, int code, int repeat, int metaState, int device, int scancode) 18、DispatchFlip(boolean keyboardOpen) 19、DispatchPress(int keyCode) 20、LaunchActivity(String pkg_name, String cl_name) 21、UserWait(long sleeptime) 22、LongPress(int keyCode)

  首先本地编写需要的测试的事件命名为 monkey.script (文件格式无要求),将文件push到手机或模拟器的sdcard中

  如: adb push e:\monkey.script /sdcard/

  然后执行脚本:adb shell monkey -v -f /sdcard/monkey.script

  Monkey脚本的命令

  脚本命令必须为小写字母

  脚本命令以回车符作为一条命令的结束

  5. monkey常用操作命令简介

  如下截图所示:

  -p 包名:指定应用程序。例如:adb shell monkey -p 包名 事件总数

  -v:打印log级别,-v越多日志信息越详细,最多3个。例如:adb shell monkey -p 包名 -v -v -v 事件总数

  -s:伪随机数生成器的 seed 值,通俗的说就是个标记,后面跟数字,例如:执行adb shell monkey -s 1 -p 包名 事件总数,这个我标记了-s 1,命令操作完之后,我发现有日志报错,我想重新执行这个monkey操作,那你就可以继续执行这个命令,排错时常用。

  -f:后接测试脚本名,例如:adb shell monkey -f 脚本名 事件总数

  --throttle:翻译减速的意思,后面接时间,单位为ms,,表示事件之间的固定延迟,如果不接该项,monkey将不会延迟,例如:adb shell monkey --throttle 500 -p 包名 事件总数

  --pct-事件类别 11个事件百分比控制(有的是9种事件,没有--pct-pinchzoom,--pct-rotation事件)由安卓SDK决定

  11种事件,按顺序罗列的

  --pct-touch {+百分比}:0

  翻译触摸,触摸事件泛指发生在某一位置的一个down-up事件,点击,

  例子:adb shell monkey -p com.htc.Weather --pct-touch 10 1000

  --pct-motion {+百分比}:1

  翻译动作,动作事件泛指从某一位置接下(即down事件)后经过一系列伪随机事件后弹出(即up事件)

  例子:adb shell monkey -p com.htc.Weather --pct-motion 20 1000

  --pct-pinchzoom {+百分比}:2

  翻译二指缩放,智能机上的放大缩小手势操作事件

  --pct-trackball {+百分比}: 3

  翻译轨迹,轨迹事件包括一系列的随机移动,以及偶尔跟随在移动后面的点击事件

  例子:adb shell monkey -p com.htc.Weather --pct-trackball 30 1000

  --pct-rotation {+百分比}:4

  翻译屏幕旋转,横屏竖屏事件

  例子:adb shell monkey -p com.htc.Weather --pct-rotation 40 1000

  --pct-nav {+百分比}:5

  翻译基本导航,基本导航事件主要来自方向输入设备的上、下、左、右事件

  例子:adb shell monkey -p com.htc.Weather --pct-nav 40 1000

  --pct-majornav {+百分比}:6

  翻译主要导航,主要导航事件通常指引发图形界面的一些动作,如键盘中间按键、返回按键、菜单按键等

  例子:adb shell monkey -p com.htc.Weather --pct-majornav 50 1000

  --pct-syskeys {+百分比}:7

  翻译系统按键,系统按键事件通常指仅供系统使用的保留按键,如HOME键、BACK键、拨号键、挂断键、音量键等

  例子:adb shell monkey -p com.htc.Weather --pct-syskeys 60 1000

  --pct-appswitch {+百分比}:8

  翻译应用启动,应用启动事件(activity launches)即打开应用,通过调用startActivity()方法最大限度地开启该package下的所有应用

  例子:adb shell monkey -p com.htc.Weather --pct-appswitch 70 1000

  --pct-flip {+百分比}:9

  翻译翻转,键盘轻弹百分比,如点击输入框,键盘弹起,点击输入框以外区域,键盘收回

  --pct-anyevent {+百分比}:10

  翻译其他类型事件,其他类型事件指上文中未涉及的所有其他事件,如keypress、不常用的button等

  例子:adb shell monkey -p com.htc.Weather

  百分比控制以及使用

  首先注意一点,这个Event percentages在不同版本的SDK版本中顺序可能会不一样。如果在monkey参数中不指定事件参数,这些动作都是随机分配的,11个动作其分配的百分比之和为100%,通过添加命令选项来控制每个事件的百分比。

  添加事件百分比之后的情况,举例添加--pct-touch事件百分比为100:

  命令: adb shell monkey -v -p 包名 --pct-touch 100 100

  --ignore-crashes:翻译忽略崩溃,当应用程序崩溃或发生失控异常时,monkey将继续运行直到计数完成。如果不设置此项,monkey遇到上述崩溃或异常将停止运行。

  --ignore-timeouts:翻译忽略超时,当应用程序发生任何超时错误(如ANR,即Application Not Responding)时,monkey将继续运行直到计数完成。如果不设置此项,monkey 遇到此类超时将停止运行。

  6.从手机上获取需要测试的package

  方法一:通过logcat命令。

  具体操作方法如下:

  在PC机器上执行命令:adb shell "logcat

   grep START" ,打开手机端需要测试的应用,找到最后一个ActivityManager中

  cmp前半部分对应的内容 $logcat

   grep START #此↑命令执行后,会在cmd窗口展开类似日志的内容,

  如果还未找到对应的包名,可以退出重新打开被测应用,找最后一个ActivityManager

  方法二:直接查看手机中存在的apk包。

  进入adb shell 命令后---手机的data/data文件夹--ls查看所有包名 找到要测apk的包名

  这种方法需要root权限,否则无法查看。所以在测试的时候还是建议第一种

  方法三:通过airtest 工具也可以获取

  7.Monkey的日志分析

  a、问题定位:

  一般测试结果分析-搜索关键字:

  程序无响应,ANR问题:在日志中搜索“ANR”

  ---》ANR是Android的一个错误,在页面无法响应事件的时候会报出来。一般遇到这样的情况,表示当前有耗时操作在UI线程指定,导致卡UI了。在Monkey中,如果遇上ANR,同样会停止继续执行。如果想要忽略ANR,让其触发的时候依然执行下去,可以使用—ignore-timeouts参数,同样它也会导致-s失效。

  语句实例:adb shell monkey —ignore-timeouts <event-count>

  崩溃问题:在日志中搜索“CRASH”

  ---》正常来说,如果在Monkey执行的阶段,出现了崩溃,会立即停止接下去的执行。但是有时候,我们在执行Monkey的时候,是在无人员干涉的情况下,例如想要它执行一夜,等等情况。那么如果出现崩溃就停止执行,明显不是我们需要的。在Monkey中,可以通过—ignore-crashes来忽略掉异常崩溃。如果用此参数忽略了崩溃,在发生崩溃的时候,会继续指定,表现是又从新开始执行Monkey了,而同时,用-s设定的seed值将不会生效

  语句实例:adb shell monkey —ignore-crashes <event-count>

  其他问题:在日志中搜索”Exception”

  b、重现问题

  Monkey测试出现错误后,一般的查错步骤为以下几步:

  1、找到是monkey里面的哪个地方出错

  2、查看Monkey里面出错前的一些事件动作,并手动执行该动作

  3、若以上步骤还不能找出,可以使用之前执行的monkey命令再执行一遍,注意seed值要一样

  4、monkey执行的过程中手机上是可以看到一些操作的,所以也可以通过这种笨办法去试试复现问题

  c、测试结果初步判断

  monkey执行时未加--ignore-crashes --ignore-crashes参数,就先浏览日志中Events injected: 值,查看当前已执行的次数,就知道有无bug

  程序无响应的问题:在日志中搜索 “ANR”

  崩溃问题:在日志中搜索 “Exception” ,在这里顺便提一下常见的Java异常:

  算术异常类:ArithmeticExecption

  空指针异常类:NullPointerException

  类型强制转换异常:ClassCastException

  数组负下标异常:NegativeArrayException

  数组下标越界异常:ArrayIndexOutOfBoundsException

  违背安全原则异常:SecturityException

  文件已结束异常:EOFException

  文件未找到异常:FileNotFoundException

  字符串转换为数字异常:NumberFormatException

  操作数据库异常:SQLException

  输入输出异常:IOException

  违法访问错误:IllegalAccessError

  内存不足错误:OutOfMemoryError

  堆栈溢出错误:StackOverflowError

  特殊场景备注:

  应用程序app的压力/健壮性测试时:单个apk的,主要缩短monkey测试中事件与事件之间的延迟时间,

  验证在快速的事件响应的过程中,程序是否能正常运行。将--throttle的值设定为500或者更小

  (一般一次抬起和放下最快大概是300毫秒,这个时间无绝对),一般都使用500毫秒的延迟事件。

标签: 交互设计