您的位置:首页 > 移动开发 > Android开发

Android自动化测试工具——Monkey

2017-06-24 23:03 477 查看

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
9a1d
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运行结果的查看结束。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android 自动化测试