Android自动化测试工具——Monkey

来源:互联网 发布:arctime字幕软件破解 编辑:程序博客网 时间:2024/06/07 05:16

Android自动化测试工具——Monkey

上一周的软件测试课刚刚练习过移动应用的测试,通过Android SDK中的uiautomatorviewer(一个由Android提供的、用来扫描和分析Android应用程序的UI组件的GUI工具)来获取界面中的一个元素,然后通过点击按钮,读取、修改文本等来模拟真实用户和应用之间的交互。今天来说说另一个工界和学界中常用的Android测试工具——Monkey


Monkey简介

Monkey测试是Android平台下自动化测试的一种快速有效的手段,可运行在模拟器和实体设备上。通过Monkey工具可以模拟用户触摸屏幕、滑动轨迹球、按键等操作来对模拟器或者手机设备上的软件进行压力测试,检测该软件的稳定性、健壮性。它的原理是向系统发送伪随机的用户事件流(如按键输入、触摸输入、手势输入等),实现对正在开发的应用程序进行压力测试。因为这个工具在App中乱按、乱摸、乱滚、乱跳,像一个调皮的猴子,所以被称为Monkey。

Monkey工具的特点

  • 1.测试对象为程序包,有一定局限性
  • 2.使用的事件流数据流是随机的,不能自定义
  • 3.可对事件数量、类型、频率设置

补充:MonkeyRunner官方文档的网址
http://developer.android.com/guide/developing/tools/monkeyrunner_concepts.html

Monkey的基本语法

参数名 基本功能 -p 参数-p用于约束限制,用此参数指定一个或多个包(Package,即App)。指定包之后,Monkey将只允许系统启动指定的App。如果不指定包,Monkey将允许系统启动设备中的所有APP。 -v 用于指定反馈信息级别(信息级别就是日志的详细程度),总共分3个级别:level0-2 -s <\seed> 用于指定伪随机数生成器的seed值,如果seed相同,则两次Monkey测试产生的时间序列也相同。 -throttle <毫秒> 用于指定用户操作(即事件)间的时延,单位是毫秒 –ignore-crashes 用于指定当应用程序奔溃时(Force & Close错误),Monkey是否停止运行。如果使用此参数,即使应用程序奔溃,Monkey依然会发送事件,直到事件计数完成。 –ignore-timeouts 用于指定当前应用程序发生ANR(Application No Responding)错误时,Monkey是否停止运行,如果使用此参数,即使应用程序发生ANR错误,Monkey依然会发送事件,直到事件计数完成。 –ignore-security-exceptions 用于指定当程序发生许可错误时(如证书许可,网络许可等),Monkey是否停止运行。如果使用此参数,即使应用程序发送许可错误,Monkey依然会发送事件,直到事件计数完成 –kill-process-after-error 用于指定应用程序发生错误时,是否停止其运行。如果指定此参数,当应用程序发生错误时,应用程序停止运行并保持在当前状态(注意:应用程序仅是静止在发生错误时的状态,系统并不会结束该应用程序的进程)。 –monitor-native-crashes 用于指定是否监视并报告应用程序发生崩溃的本地代码 –pct- {+事件类别} {+事件类别百分比} 用于指定每种类别事件的数目百分比(在Monkey事件序列中,该类事件数据占总事件数目的百分比) –pct-touch {+百分比} 调整触摸时间的百分比(触摸事件是一个down-up事件,它发生在屏幕上的某个单一位置) –pct-motion 调整动作事件的百分比(动作事件由屏幕上某处的一个down事件、一系列的伪随机事件和一个up事件组成) –pct-trackball {+百分比 } 调整轨迹事件的百分比(轨迹事件由一个或者几个随机的移动组成,有时还伴随有点击) –pct-nav 调整“基本”导航事件的百分比(导航事件由来自方向输入设备up/down/left/right组成) –pct-majornav {+百分比} 调整“主要”导航事件的百分比(这些导航事件通常引发图形界面中的动作,如:5-way键盘的中间按键、回退按键、菜单按键) –pct-syskeys {+百分比} 调整“系统”按键事件的百分比(这些按键通常被保留,由系统使用,如Home、Back、Start Call、End Call及音量 –pct-appswitch {+百分比} 调整启动Activity的百分比。在随机间隔里,Monkey将执行一个startActivity()调用,作为最大程度覆盖包中全部Activity –pct-anyevent {+百分比} 调整其它类型事件的百分比。它包罗了所有其它类型的事件,如:按键、其它不正常的设备按钮,等等 –wait-dbg 停止执行中的Monkey,直到有调试器和它相连接。

(!!!注:这里由于博客编辑器的原因,“-s ”的参数seed前面加了一个“\”,正常情况下没有这个符号。)

Monkey测试示例图解

我选择的app是开源中国(上周测试考试用到的apk)

(1)将apk安装到模拟器中。安装后,能够在模拟器中看到安装好的apk,如下图:
这里写图片描述

(2)安装好apk文件后,需要知道应用程序主Activity(第一个启动的Activity)所在的包名。

获取包名有多种方法,可以参照这个网址中提到的指令。
http://www.51testing.com/html/93/136593-3714533.html

这里得到的包名如下图:
这里写图片描述

(3) 使用moneky命令进行自动化压力测试。

命令为:

#monkey -p net.oschina.app.improve -v 100//(参数说明:-p后跟软件所在包名,-v后跟测试的次数)。这里对该软件发送了100次的伪随机事件,即进行了100次的自动化测试。

(4) 查看测试的结果。
我的测试结果如下图:
这里写图片描述
如果测试没有通过,会报错。如果输出了“Monkey Finished”则说明测试通过,这里的测试通过。

但是查看结果还是有不明白的地方,如Event Percentages的0-10各代表什么?
这一点,我们可以查看android-4.2.2_r1.2中的MonkeySourceRandom.java中定义的这些值:

public static final int FACTOR_TOUCH        = 0;  public static final int FACTOR_MOTION       = 1;  public static final int FACTOR_PINCHZOOM    = 2;  public static final int FACTOR_TRACKBALL    = 3;  public static final int FACTOR_ROTATION     = 4;  public static final int FACTOR_NAV          = 5;  public static final int FACTOR_MAJORNAV     = 6;  public static final int FACTOR_SYSOPS       = 7;  public static final int FACTOR_APPSWITCH    = 8;  public static final int FACTOR_FLIP         = 9;  public static final int FACTOR_ANYTHING     = 10;  public static final int FACTORZ_COUNT       = 11;    // should be last+1  private static final int GESTURE_TAP = 0;  private static final int GESTURE_DRAG = 1;  private static final int GESTURE_PINCH_OR_ZOOM = 2; 

然后再来看Monkey.java源码中的processOptions()方法

private boolean processOptions() {      // quick (throwaway) check for unadorned command      if (mArgs.length < 1) {          showUsage();          return false;      }      try {          String opt;          while ((opt = nextOption()) != null) {              if (opt.equals("-s")) {                  mSeed = nextOptionLong("Seed");              } else if (opt.equals("-p")) {                  mValidPackages.add(nextOptionData());              } else if (opt.equals("-c")) {                  mMainCategories.add(nextOptionData());              } else if (opt.equals("-v")) {                  mVerbose += 1;              } else if (opt.equals("--ignore-crashes")) {                  mIgnoreCrashes = true;              } else if (opt.equals("--ignore-timeouts")) {                  mIgnoreTimeouts = true;              } else if (opt.equals("--ignore-security-exceptions")) {                  mIgnoreSecurityExceptions = true;              } else if (opt.equals("--monitor-native-crashes")) {                  mMonitorNativeCrashes = true;              } else if (opt.equals("--ignore-native-crashes")) {                  mIgnoreNativeCrashes = true;              } else if (opt.equals("--kill-process-after-error")) {                  mKillProcessAfterError = true;              } else if (opt.equals("--hprof")) {                  mGenerateHprof = true;              } else if (opt.equals("--pct-touch")) {                  int i = MonkeySourceRandom.FACTOR_TOUCH;                  mFactors[i] = -nextOptionLong("touch events percentage");              } else if (opt.equals("--pct-motion")) {                  int i = MonkeySourceRandom.FACTOR_MOTION;                  mFactors[i] = -nextOptionLong("motion events percentage");              } else if (opt.equals("--pct-trackball")) {                  int i = MonkeySourceRandom.FACTOR_TRACKBALL;                  mFactors[i] = -nextOptionLong("trackball events percentage");              } else if (opt.equals("--pct-rotation")) {                  int i = MonkeySourceRandom.FACTOR_ROTATION;                  mFactors[i] = -nextOptionLong("screen rotation events percentage");              } else if (opt.equals("--pct-syskeys")) {                  int i = MonkeySourceRandom.FACTOR_SYSOPS;                  mFactors[i] = -nextOptionLong("system (key) operations percentage");              } else if (opt.equals("--pct-nav")) {                  int i = MonkeySourceRandom.FACTOR_NAV;                  mFactors[i] = -nextOptionLong("nav events percentage");              } else if (opt.equals("--pct-majornav")) {                  int i = MonkeySourceRandom.FACTOR_MAJORNAV;                  mFactors[i] = -nextOptionLong("major nav events percentage");              } else if (opt.equals("--pct-appswitch")) {                  int i = MonkeySourceRandom.FACTOR_APPSWITCH;                  mFactors[i] = -nextOptionLong("app switch events percentage");              } else if (opt.equals("--pct-flip")) {                  int i = MonkeySourceRandom.FACTOR_FLIP;                  mFactors[i] = -nextOptionLong("keyboard flip percentage");              } else if (opt.equals("--pct-anyevent")) {                  int i = MonkeySourceRandom.FACTOR_ANYTHING;                  mFactors[i] = -nextOptionLong("any events percentage");              } else if (opt.equals("--pct-pinchzoom")) {                  int i = MonkeySourceRandom.FACTOR_PINCHZOOM;                  mFactors[i] = -nextOptionLong("pinch zoom events percentage");              } else if (opt.equals("--pkg-blacklist-file")) {                  mPkgBlacklistFile = nextOptionData();              } else if (opt.equals("--pkg-whitelist-file")) {                  mPkgWhitelistFile = nextOptionData();              } else if (opt.equals("--throttle")) {                  mThrottle = nextOptionLong("delay (in milliseconds) to wait between events");              } else if (opt.equals("--randomize-throttle")) {                  mRandomizeThrottle = true;              } else if (opt.equals("--wait-dbg")) {                  // do nothing - it's caught at the very start of run()              } else if (opt.equals("--dbg-no-events")) {                  mSendNoEvents = true;              } else if (opt.equals("--port")) {                  mServerPort = (int) nextOptionLong("Server port to listen on for commands");              } else if (opt.equals("--setup")) {                  mSetupFileName = nextOptionData();              } else if (opt.equals("-f")) {                  mScriptFileNames.add(nextOptionData());              } else if (opt.equals("--profile-wait")) {                  mProfileWaitTime = nextOptionLong("Profile delay" +                              " (in milliseconds) to wait between user action");              } else if (opt.equals("--device-sleep-time")) {                  mDeviceSleepTime = nextOptionLong("Device sleep time" +                                                    "(in milliseconds)");              } else if (opt.equals("--randomize-script")) {                  mRandomizeScript = true;              } else if (opt.equals("--script-log")) {                  mScriptLog = true;              } else if (opt.equals("--bugreport")) {                  mRequestBugreport = true;              } else if (opt.equals("--periodic-bugreport")){                  mGetPeriodicBugreport = true;                  mBugreportFrequency = nextOptionLong("Number of iterations");              } else if (opt.equals("-h")) {                  showUsage();                  return false;              } else {                  System.err.println("** Error: Unknown option: " + opt);                  showUsage();                  return false;              }          }      } catch (RuntimeException ex) {          System.err.println("** Error: " + ex.toString());          showUsage();          return false;      }      // If a server port hasn't been specified, we need to specify      // a count      if (mServerPort == -1) {          String countStr = nextArg();          if (countStr == null) {              System.err.println("** Error: Count not specified");              showUsage();              return false;          }          try {              mCount = Integer.parseInt(countStr);          } catch (NumberFormatException e) {              System.err.println("** Error: Count is not a number");              showUsage();              return false;          }      }      return true;  }  

所以,Monkey运行结果中对应的就应该是:

数字 对应量 解释 0 –pct-touch//touch events percentage 触摸事件百分比(触摸事件是一个在屏幕单一位置的按下-抬起事件) 1 –pct-motion//motion events percentage 手势事件百分比(手势事件是由一个在屏幕某处的按下事件、一系列的伪随机移动、一个抬起事件组成)即一个滑动操作,但是是直线的,不能拐弯 2 –pct-pinchzoom//pinch zoom events percentage 二指缩放百分比,即智能机上的放大缩小手势操作 3 –pct-trackball//trackball events percentage 轨迹球事件百分比(轨迹球事件包括一个或多个随机移动,有时还伴有点击。轨迹球现在智能手机上已经没有了,就是类似手柄的方向键一样) 4 –pct-rotation//screen rotation events percentage 屏幕旋转百分比,横屏竖屏 5 –pct-nav//nav events percentage “基本”导航事件百分比(导航事件包括上下左右,如方向输入设备的输入)老手机的上下左右键,智能机上没有 6 –pct-majornav//major nav events percentage “主要”导航事件百分比(这些导航事件通常会引发UI的事件,例如5-way pad的中间键、回退键、菜单键) 7 –pct-syskeys//system(key) operations percentage “系统”按钮事件百分比(这些按钮一般专供系统使用,如Home, Back, Start Call, End Call,音量控制) 8 –pct-appswitch//app switch events percentage 启动activity事件百分比。在随机的间隔里,Monkey会执行一个startActivity()调用,作为最大程度覆盖包中全部Activity的一种方法 9 –pct-flip//keyboard flip percentage 键盘轻弹百分比,如点击输入框,键盘弹起,点击输入框以外区域,键盘收回 10 –pct-anyevent//anyevents percentage 其他类型事件百分比。包括了其他所有的类型事件,如按键、其他不常用的设备上的按钮等等。

至此,monkey运行结果的查看结束。

原创粉丝点击