前言

Monkey是 Android SDK 提供的一个命令行工具,是 Android 自动化测试的一种手段 。Monkey 命令通过向安卓设备/安卓模拟器发送伪随机的用户事件流(如按键输入、触摸屏输入、手势输入等)。对Android APP做稳定性(压力)测试。【主要是为了测试app是否存在无响应和崩溃闪退等异常情况。】

产品处于稳定状态,没有太多BUG后,一般使用monkey命令去测试产品的稳定性、健壮性(是否会发生闪退、崩溃和无响应等问题),实现对正在开发的安卓应用程序进行压力测试和稳定性测试 。

获取测试日志的ANR、CRASH、Exception信息,提供给开发人员分析和定位问题。【一般一次Monkey测试中0 ANR 、0 CRASH是测试标准】

Monkey测试是一种为了测试软件的稳定性、健壮性的快速有效的方法。

Monkey 简介

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

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

③Monkey测试是一种为了测试软件的稳定性、健壮性的快速有效的方法。

④Monkey用于进行压力测试。开发人员可以结合Monkey打印的日志和系统打印的日志,分析测试中的问题。

Monkey的特点

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

Monkey.jar程序是由一个名为“monkey”的Shell脚本来启动执行,shell脚本在Android文件系统中的存放路径是/system/bin/monkey。

总结:通过①②说明monkey可以直接通过打包进测试工具中,可以被测试人员直接使用。

   网络上许多第三方的monkey工具就是通过对原生的Monkey.jar包进行二次开发实现。

Monkey测试的特点

①Monkey 测试,所有的事件都是随机产生的,不带任何主观性。

②测试的对象仅为应用程序包,有一定的局限性。

③Monky 测试使用的事件数据流是随机的,不能进行自定义。

③可对 Monkey 测试的对象(启动系统指定的包名),事件数量,类型,频率等进行设置。

Monkey 架构

Monkey 运行在安卓设备或模拟器中,可以脱离PC端运行。(一般在一些大公司中都是将其抽离成一个测试专用的APP工具,使用相应的操作来完成测试)

monkey命令_android

Monkey的基本用法

adb shell monkey [options]

【注意】如果不指定options参数,Monkey将以无反馈模式启动,并把事件任意发送到安装在目标环境中的全部包对应的安卓app。

如下示例:启动指定的应用程序,并向其发送500个伪随机事件:

Monkey 命令行:

adb shell monkey -p 包名 --throttle 时间间隔 -s 随机数种子 -v -v -v 次数 > 日志文件名

Monkey 测试结果分析:

①正常结果:在日志文件最后一行出现 Monkey finished,表示设备运行正常。

monkey命令_monkey测试_02

②异常结果:日志中遇到 Crash 或者 ANR 自动终止运行。

Monkey 测试指标:

①可以按操作次数或操作时间来规定指标。

②一般情况 3 万次以内出现 Crash,认为安卓应用系统的可靠性比较差。

举例:

monkey命令_monkey测试_03

adb shell monkey -p your.package.name -v 500

Monkey常用命令行:

monkey命令_应用程序_04

1、参数:-p

用于约束限制,Monkey用此参数指定一个或多个包名(Package,即App)。

指定包之后,Monkey将只允许系统启动指定的APP,如果不指定包名,将允许系统启动设备中的所有APP。【会把任意事件发送到所有的app】

举例:

* 指定一个包:  adb shell monkey -p cn.emoney.acg 10 

* 指定多个包: adb shell monkey -p cn.emoney.acg –p cn.emoney.wea -p cn.emoney.acg 100 

* 不指定包: adb shell monkey 100 

2、参数:-v

用于指定反馈信息级别(信息级别就是日志的详细程度),总共分3个级别,分别对应的参数如下表所示:

①日志级别 Level0(1V):说明缺省值,仅提供启动提示、测试完成和最终结果等少量信息。(Level 0(缺省值)除 启动提示、测试完成和最终结果之外,提供较少信息)

举例: adb shell monkey -p cn.emoney.acg –v 100 

②日志级别 Level1(2V):说明提供较为详细的日志,包括每个发送到Activity的事件信息。(Level 1提供较为详细的测试信息,如逐个发送到Activity的事件)

举例: adb shell monkey -p cn.emoney.acg –v -v 100 

③日志级别 Level 2(3V):说明最详细的日志,包括了测试中选中/未选中的Activity信息。(Level 2提供更加详细的设置信息,如测试中被选中的或未被选中的Activity)

举例: adb shell monkey -p cn.emoney.acg –v -v –v 100 

3、参数:-s

测试人员为了能够重现测试到的bug问题,需要能够对Monkey的随机生成事件有重现能力:monkey允许对随机事件的seed值做设置,当两次seed值一样,整个测试效果将会产生相同的事件序列。

用于指定伪随机数生成器的seed值,如果seed相同,则两次Monkey测试所产生的事件序列也相同的。【伪随机数生成器的seed值Money命令向系统发送伪随机的用户事件流的顺序】

举例:为随机数的事件序列定一个值,若出现问题下次可以重复同样的系列进行排错。(伪随机数生成器的seed值。如果用相同的seed值再次运行Monkey,它将生成相同的事件序列)

Monkey 测试1: adb shell monkey -p cn.emoney.acg -s 10 100 

Monkey 测试2: adb shell monkey -p cn.emoney.acg –s 10 100 

两次测试的效果是相同的,因为模拟的用户操作序列(每次操作都会按照一定的先后顺序所组成的一系列操作,即一个序列)是一样的。如下:

可以看到,在每次执行完Monkey命令之后,从输出里可以看到当前的seed值,只要通过​​-s​​参数指定相同的seed,就可以重复刚才的操作。

monkey命令_android_05

例如如果需要重复上面的操作,就需要在Terminal中输入:

adb shell monkey -p com.geely.consumer -s 1639012303781 -v -v 1000000

4、参数: --throttle<毫秒>

事件之间加入延时操作:在某些不需要频率过快,或需要指定频率进行交互时,可以采用--throttle来做事件之间的延时操作。

用于指定用户操作(即事件)间的时延(延迟时间),单位是毫秒;

举例:【为每一次执行一次有效的事件后休眠5000毫秒】

adb shell monkey -p cn.emoney.acg --throttle 5000 100

在随机事件之间插入固定延迟。通过这个选项可以减缓Monkey的执行速度。

如果不指定该选项,Monkey将不会被延迟,事件将尽可能快地被产成。

一般业内标准是每秒操作2-3次。即:--throttle 200到 --throttle 300

5 、参数: --ignore-crashes

忽略程序崩溃。

正常来说,如果在 Monkey 命令执行的阶段,安卓应用程序出现了崩溃,会立即停止接下去的执行。但是有时候,我们在执行Monkey的时候,是在无人员干涉的情况下,例如想要它执行一夜等等情况。那么如果出现崩溃就停止执行,明显不是我们需要的。

用于指定当应用程序崩溃时(Force& Close错误),Monkey是否停止运行。

如果使用此参数,即使应用程序崩溃,Monkey依然会发送事件,直到事件计数完成。但是对于重新执行的 Monkey 命令-s参数设置的随机数seed值将不会生效。

举例:

测试过程中即使程序崩溃,Monkey依然会继续发送事件直到事件数目达到1000为止: adb shell monkey -p cn.emoney.acg --ignore-crashes 1000 

测试过程中,如果acg程序崩溃,Monkey将会停止运行: adb shell monkey -p cn.emoney.acg 1000 

6、参数: --ignore-timeouts

忽略程序超时。【这里的超时并不是网络超时或者接口返回超时,而是程序相应超时导致的ANR】

ANR是Android应用程序的一个错误,在页面无法响应事件的时候会报出来。一般遇到这样的情况,表示当前有耗时操作在UI线程指定,导致卡UI了。

用于指定当应用程序发生ANR(Application No Responding)错误时,Monkey是否停止运行。如果使用此参数,即使应用程序发生ANR错误,Monkey依然会发送事件,直到事件计数完成。

举例:

adb shell monkey -p cn.emoney.acg --ignore-timeouts 1000

7、参数: --ignore-security-exceptions

用于指定当应用程序发生许可错误时(如证书许可,网络许可等),Monkey是否停止运行。

如果使用此参数,即使应用程序发生许可错误,Monkey依然会发送事件,直到事件计数完成。

举例:

adb shell monkey -p cn.emoney.acg --ignore-security-exception 1000

8、参数: --kill-process-after-error

用于指定当应用程序发生错误时,是否停止其运行。

如果指定此参数,当应用程序发生错误时,应用程序停止运行并保持在当前状态。

【注意】应用程序仅是静止在发生错误时的状态,系统并不会结束该应用程序的进程。

举例:

adb shell monkey -p cn.emoney.acg --kill-process-after-error 1000

9、参数: --monitor-native-crashes

用于指定是否监视并报告应用程序发生崩溃的本地代码。

举例:

adb shell monkey -p cn.emoney.acg --monitor-native-crashes 1000

10、参数: --pct-{事件类别}{事件类别百分比}:用于指定每种类别事件的数目百分比(在Monkey事件序列中,该类事件数目占总事件总数目的百分比)

指定发生事件的类型【限制Monkey测试随机执行的事件类型和占比,–pct-xxx参数

Monkey测试是希望模拟用户操作,在实际测试过程中需要让Monkey执行的事件尽可能地接近用户的常规操作,这样才可以最大限度地发现用户使用过程中可能出现的问题。因此我们需要对Monkey执行的事件比例做一些调整。实际比例可按照被测App情况调整,不能超过100%。

monkey命令_应用程序_06

虽然Monkey测试是随机事件,但是我们可以指定事件的类型。【注意】:①所有指定事件的数值加起来不能超过100。②不做任何指定时,默认为--pct-anyevent <percent> 类型,百分比为百分之百,也就是纯随机事件。③如果通过其他的参数配置了之后,如果相加的百分比不为百分百,余下的百分比部分也会生成随机事件。

--pct-touch <percent>:指定触摸事件的百分比。

--pct-motion <percent>:指定滑动事件的百分比。

--pct-trackball <percent>:指定轨迹球事件的百分比。

--pct-nav <percent>:指定导航事件中,up、down、left、right等事件的百分比。

--pct-majornav <percent>:指定导航事件中,back、menu等事件的百分比。

--pct-syskeys <percent>:指定系统按键的百分比,包括HOME、Back、音量等。

--pct-appswitch <percent>:指定Activity之间切换的比例。

--pct-anyevent <percent>:指定任意事件的百分比。

①--pct-touch{百分比}

调整触摸事件的百分比(触摸事件是一个down-up事件,它发生在屏幕上的某单一位置)

adb shell monkey -p cn.emoney.acg --pct-touch 10 100

②--pct-motion {百分比}

调整动作事件的百分比(动作事件由屏幕上某处的一个down事件、一系列的伪随件机事和一个up事件组成)

adb shell monkey -p cn.emoney.acg --pct-motion 20 1000

③--pct-trackball {百分比}

调整轨迹事件的百分比(轨迹事件由一个或几个随机的移动组成,有时还伴随有点击)

adb shell monkey -p cn.emoney.acg --pct-trackball 30 1000

④--pct-nav{百分比}

调整“基本”导航事件的百分比(导航事件由来自方向输入设备的up/down/left/right组成)

adb shell monkey -p cn.emoney.acg --pct-nav 40 1000

⑤--pct-majornav{百分比}

调整“主要”导航事件的百分比(这些导航事件通常引发图形界面中的动作,如:5-way键盘的中间按键、回退按键、菜单按键)

adb shell monkey -p cn.emoney.acg --pct-majornav 50 1000

⑥--pct-syskeys {百分比}

调整“系统”按键事件的百分比(这些按键通常被保留,由系统使用,如Home、Back、Start Call、End Call及音量控制键)。

adb shell monkey -p cn.emoney.acg --pct-syskeys 20 1000

⑦--pct-appswitch {百分比}

调整启动Activity的百分比。在随机间隔里,Monkey将执行一个startActivity()调用,作为最大程度覆盖包中全部Activity的一种方法。

adb shell monkey -p cn.emoney.acg --pct-appswitch 20 1000

⑧--pct-anyevent {百分比}

调整其它类型事件的百分比。它包罗了所有其它类型的事件,如:按键、其它不常用的设备按钮、等等。

adb shell monkey -p cn.emoney.acg --pct-anyevent 100 1000

11、参数: --hprof

设置此选项,将在Monkey事件序列之前和之后立即生成profiling报告。这将会在data/misc中生成大文件(~5Mb),所以要小心使用它。

Monkey调试选项

1、一般情况下,安卓APP在操作过程中会存在崩溃、超时、异常等情况,按照前面所提到的,这会导致monkey直接停止测试。如果想要忽略掉这些情况,直接配置忽略设置就可以。

①--dbg-no-events:初始化启动的activity,但是不产生任何事件。
②--hprof:指定该项后在事件序列发送前后会立即生成分析报告 —— 一般建议指定该项。
③--ignore-crashes:忽略崩溃
④--ignore-timeouts:忽略超时
⑤--ignore-security-exceptions:忽略安全异常
⑥--kill-process-after-error:发生错误后直接杀掉进程
⑦--monitor-native-crashes:跟踪本地方法的崩溃问题
⑧--wait-dbg:知道连接了调试器才执行monkey测试。

2、可以输入下面命令查看Monkey测试的其他命令行:

adb shell monkey -help

运行结果:

usage: monkey [-p ALLOWED_PACKAGE [-p ALLOWED_PACKAGE] ...]//调试的应用包名
[-c MAIN_CATEGORY [-c MAIN_CATEGORY] ...]//测试对应的categrory
[--ignore-crashes] [--ignore-timeouts]
[--ignore-security-exceptions]
[--monitor-native-crashes] [--ignore-native-crashes]//忽略系列的大爷们
[--kill-process-after-error] [--hprof]//默认
[--pct-touch PERCENT] [--pct-motion PERCENT]
[--pct-trackball PERCENT] [--pct-syskeys PERCENT]
[--pct-nav PERCENT] [--pct-majornav PERCENT]
[--pct-appswitch PERCENT] [--pct-flip PERCENT]
[--pct-anyevent PERCENT] [--pct-pinchzoom PERCENT]//事件百分比设置
[--pkg-blacklist-file PACKAGE_BLACKLIST_FILE]
[--pkg-whitelist-file PACKAGE_WHITELIST_FILE]
[--wait-dbg] [--dbg-no-events]
[--setup scriptfile] [-f scriptfile [-f scriptfile] ...]
[--port port]
[-s SEED] [-v [-v] ...]//设置随机数生成器的seed值
[--throttle MILLISEC] [--randomize-throttle]//延时操作
[--profile-wait MILLISEC]
[--device-sleep-time MILLISEC]
[--randomize-script]
[--script-log]
[--bugreport]
[--periodic-bugreport]
COUNT

3、当开始执行Monkey测试后,会顺序输出执行的事件流信息,如:

#执行的事件流信息
#启动App事件
Switch: #Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.geely.consumer/com.geely.market.deploy.activity.DevContainActivity;end
// Allowing start of Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.geely.consumer/com.geely.market.deploy.activity.DevContainActivity } in package com.geely.consumer
// Allowing start of Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.geely.consumer/com.geely.market.deploy.activity.DevContainActivity } in package com.geely.consumer
#点击事件
:Sending Touch (ACTION_DOWN): 0:(308.0,2215.0)

输出Monkey Log

跑monkey的时候或者想抓程序log导出时,有时会提示: cannot create D:monkeytest.txt: read-only file system

为什么有时候可以有时候不可以?后来发现跟使用使用习惯不一样,一会是先进入adb shell 再用命令,一会是直接命令进入。

【注意】如果进入adb shell后再使用Monkey命令测试应用就会导致到处Monkey Log到本地失败。【进入adb shell后就相当于进入安卓手机的linux原生系统的root下面,此时默认导出Monkey日志到手机,但是并没有权限在手机里创建文件】

正确方法:退出shell或者执行命令时先不要进shell,而是直接使用adb shell monkey运行Monkey命令测试。【直接使用adb shell monkey命令可以导出Monkey日志到本地电脑中】

①命令重定向符,将其前面的命令的输出结果重新定向到其后面的设备中去,后面的设备中的内容被覆盖。

C:\Documents and Settings\Administrator>adb shell monkey -p 包名 -v 300 >e:\text.txt

②命令重定向符。将其前面的命令的输出结果重新定向到其后面的设备中去,后面设备中的内容没有被覆盖。即追加输出。

C:\Documents and Settings\Administrator>adb shell monkey -p 包名 -v 300 >> e:\text.txt

Monkey测试的停止条件

①如果限定了Monkey运行在一个或几个特定的包上,那么它会监测试图转到其它包的操作,并对其进行阻止。

②如果应用程序崩溃或接收到任何失控异常,Monkey将停止并报错。(前提在于没有配置crash继续执行的操作)

③如果应用程序产生了应用程序不响应(application not responding)的错误,Monkey将会停止并报错。(前提在于没有配置ANR继续执行的操作)

强制退出Monkey测试

退出应用和拔掉数据线,都无法停止monkey测试,试图用control+C 命令,控制台虽然能再次输入命令,可是手机还是在继续monkey命令。

网上大部分人认为monkey开始测试之后,就不能停止,除非时间数执行完成,或者在cmd窗口执行adb reboot来进行手机重启操作。

如需停止monkey测试,输入如下命令(用B站举列子):

①开始执行Monkey测试

adb shell monkey -p tv.danmaku.bili --throttle 1000 500

②输入control+C,控制台不再输出执行的信息,可以再次输入命令(但是手机还在跑Monkey命令)

③查看安卓手机中的monkey进程号:adb命令返回来的数字,即是monkey的进程号

adb shell ps | grep monkey

运行结果;

monkey命令_android_07

④如上图17390就是安卓手机运行Monkey命令的进程号,可以运行kill 命令来杀死该进程:

adb shell kill 17390

⑤检查安卓手机中的monkey进程是否已被杀死,即安卓手机不再继续执行Monkey测试:

adb shell ps | grep monkey

Monkey测试结果分析

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

1、初步分析方法:(错误重现)

①找到是monkey里面的哪个地方出错。

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

③若以上步骤还不能找出,可以使用之前执行的monkey命令再执行一遍,注意seed值要一样(复现Monkey测试中出现的错误)

 2、一般的测试结果分析:

关键字查询:当Monkey命令执行过程中遇到错误时,会输出对应异常信息,关键字查询:应用程序无响应(ANR)、崩溃(CRASH)、其他问题(Exception)

  • ANR:指当Android系统监测到应用程序在5秒内没有响应输入的事件或广播在10秒内没有执行完毕时抛出无响应弹窗提示
  • CRASH:应用程序出现错误时导致程序崩溃、异常停止或退出的情况
  • Exception:其他问题的一些问题

【理论上来讲,当获取到app在monkey测试过程中的CRASH和ANR日志信息后,开发人员就可以开始根据日志内容分析和定位问题了。】

① ANR问题:在日志文件中搜索“ANR”

②崩溃问题:在日志文件中搜索“Exception” 、“Force Close”

Monkey测试实例

1、允许启动安卓设备或者模拟器里面所有的 App , 随机操作 1000 次。

adb shell monkey 1000

2、打开哔哩哔哩应用,操作序列号为110,每个事件之间延迟500毫秒(就是0.5S),日志级别为一个V ,随机执行1000个事件,该日志保存到桌面的test_monkey.txt文件中。

adb shell monkey -p tv.danmaku.bili -s 110 --throttle 500 -v 1000 >/Users/mac/Desktop/test_monkey.txt

3、monkey具备同时对多个安卓应用进行调试的能力,只需要增加多个 -p 包名字段就可以实现。

adb shell monkey -p com.miui.calculator -p com.android.thememanager 1000

4、各类随机事件的输入占比总和为百分之百。

adb shell monkey -p com.miui.cal —throttle 100 —-ignore-crashes —-ignore-timeouts --pct-touch 50 --pct-majornav 10 --pct-syskeys 20 --pct-appswitch 20 -v 1000 > ./monket_log.txt

 

去期待陌生,去拥抱惊喜。