Monkey 是 Android 中的一个命令行工具,可以运行在模拟器里或实际设备中。它向系统发送伪随机的用户事件流 (如按键输入、触摸屏输入、手势输入等),实现对正在开发的应用程序进行压力测试。Monkey 测试是一种为了测试软件的稳定性、健壮性的快速有效的方法。
基本语法
$ adb shell monkey [options]
如果不指定 options,Monkey 将以无反馈模式启动,并把事件任意发送到安装在目标环境中的全部应用程序
$ adb shell monkey -p package -v 500
指定对 package 这个应用程序进行 monkey 测试,并向其发送 500 个伪随机事件。其中 -p 表示对象包包,–v 表示反馈信息级别
命令参数
可以使用命令 adb shell monkey -help 查看命令参数
1、参数: -p
用于约束限制,用此参数指定一个或多个应用。指定应用之后,monkey 将只允许系统启动指定的 app;如果不指定应用,将允许系统启动设备中的所有应用。
指定一个应用: adb shell monkey -p com.ifeng.news2 100
指定多个应用:adb shell monkey -p com.ifext.news –p com.ifeng.news2 100
不指定应用:adb shell monkey 100
2、参数:-c
用于约束限制,用此参数指定了一个或几个类别,Monkey 将只允许系统启动被这些类别中的某个类别列出的 Activity。如果不指定任何类别,Monkey 将选择下列类别中列出的 Activity:Intent.CATEGORY.LAUNCHER 或 Intent.CATEGORY.MONKEY。要指定多个类别,需要使用多个-c 选项,每个-c 选项只能用于一个类别。
3、参数:-v
用于指定反馈信息级别(信息级别就是日志的详细程度),总共分 3 个级别:
默认级别 Level 0:-v
adb shell monkey -p com.ifeng.news2 –v 100:说明仅提供启动提示、测试完成和最终结果等少量信息
日志级别 Level 1:-v -v
adb shell monkey -p com.ifeng.news2 –v -v 100:说明提供较为详细的日志,包括每个发送到 Activity 的事件信息
日志级别 Level 2:-v -v -v
adb shell monkey -p com.ifeng.news2 –v -v –v 100:说明最详细的日志,包括了测试中选中/未选中的 Activity 信息
4、参数: -s
伪随机数生成器的 seed 值。如果用相同的 seed 值再次运行 Monkey,它将生成相同的事件序列
Monkey 测试 1:adb shell monkey -p com.ifeng.news2 -s 10 100
Monkey 测试 2:adb shell monkey -p com.ifeng.news2 –s 10 100
两次测试的效果是相同的,因为模拟的用户操作序列(每次操作按照一定的先后顺序所组成的一系列操作,即一个序列)是一样的。
5、参数: --throttle<毫秒>
用于指定用户操作(即事件)间的延时,单位是毫秒
adb shell monkey -p com.ifeng.news2 --throttle 5000 100
6、参数: --ignore-crashes
用于指定当应用程序崩溃时(Force& Close 错误),Monkey 是否停止运行。如果使用此参数,即使应用程序崩溃,Monkey 依然会发送事件,直到事件计数完成。
adb shellmonkey -p com.ifeng.news2 --ignore-crashes 1000
测试过程中即使程序崩溃,Monkey 依然会继续发送事件直到事件数目达到 1000 为止
adb shellmonkey -p com.ifeng.news2 1000
测试过程中,如果 acg 程序崩溃,Monkey 将会停止运行
7、参数: --ignore-timeouts
用于指定当应用程序发生 ANR(Application No Responding)错误时,Monkey 是否停止运行。如果使用此参数,即使应用程序发生 ANR 错误,Monkey 依然会发送事件,直到事件计数完成。
adb shellmonkey -p com.ifeng.news2--ignore-timeouts 1000
8、参数: --ignore-security-exceptions
用于指定当应用程序发生许可错误时(如证书许可,网络许可等),Monkey 是否停止运行。如果使用此参数,即使应用程序发生许可错误,Monkey 依然会发送事件,直到事件计数完成。
adb shellmonkey -p com.ifeng.news2 --ignore-security-exception 1000
9、参数: --kill-process-after-error
用于指定当应用程序发生错误时,是否停止其运行。如果指定此参数,当应用程序发生错误时,应用程序停止运行并保持在当前状态(注意:应用程序仅是静止在发生错误时的状态,系统并不会结束该应用程序的进程)。
adb shellmonkey -p cn.emoney.acg --kill-process-after-error 1000
10、参数: --monitor-native-crashes
用于指定是否监视并报告应用程序发生崩溃的本地代码。
adb shellmonkey -p cn.emoney.acg --monitor-native-crashes 1000
11、参数: --pct-{+ 事件类别}{+ 事件类别百分比}
用于指定每种类别事件的数目百分比(在 Monkey 事件序列中,该类事件数目占总事件数目的百分比)
--pct-touch{+ 百分比}:
调整触摸事件的百分比 (触摸事件是一个 down-up 事件,它发生在屏幕上的某单一位置)
adb shell monkey -p com.ifeng.news2 --pct-touch 10 1000
--pct-motion {+ 百分比}:
调整动作事件的百分比 (动作事件由屏幕上某处的一个 down 事件、一系列的伪随件机事和一个 up 事件组成)
adb shell monkey -p com.ifeng.news2 --pct-motion 20 1000
--pct-trackball {+ 百分比}:
调整轨迹事件的百分比 (轨迹事件由一个或几个随机的移动组成,有时还伴随有点击)
adb shell monkey -p com.ifeng.news2 --pct-trackball 30 1000
--pct-nav {+ 百分比}:
调整 “基本” 导航事件的百分比 (导航事件由来自方向输入设备的 up/down/left/right 组成)
adb shell monkey -p com.ifeng.news2 --pct-nav 40 1000
--pct-majornav {+ 百分比}:
调整 “主要” 导航事件的百分比 (这些导航事件通常引发图形界面中的动作,如:5-way 键盘的中间按键、回退按键、菜单按键)
adb shell monkey -p com.ifeng.news2 --pct-majornav 50 1000
Monkey 运行时输出的日志一般包含四类信息,分别是测试命令信息、伪随机事件流信息、异常信息、Monkey 执行结果信息。
1)测试命令信息
Monkey 启动后会输出当前所执行命令的各种参数信息,其中包括种子(Seed)信息、事件数量、可运行的应用列表以及各事件百分比等。这些信息都是通过 Monkey 命令参数所指定的,这部分日志信息的解析,如代码清单 4-3 所示。
代码清单 4-3 Monkey 日志 - 测试命令信息
//测试命令信息
//随机种子值,执行事件数量
:Monkey: seed=1454215444564 count=10
//可运行的应用列表
:AllowPackage: com.tencent.android.qqdownloader
//Category 包含 LAUNCHER 和 MONKEY
:IncludeCategory: android.intent.category.LAUNCHER
:IncludeCategory: android.intent.category.MONKEY
//各事件的百分比
// Event percentages:
// 0: 15.0% 事件 0:--pct-touch
// 1: 10.0% 事件 1:--pct-motion
// 2: 2.0% 事件 2:--pct-pinchzoom
// 3: 15.0% 事件 3:--pct-trackball
// 4: -0.0% 事件 4:--pct-rotation
// 5: 25.0% 事件 5:--pct-nav
// 6: 15.0% 事件 6:--pct-majornav
// 7: 2.0% 事件 7:--pct-syskeys
// 8: 2.0% 事件 8:--pct-appswitch
// 9: 1.0% 事件 9:--pct-flip
// 10: 13.0% 事件 10:--pct-anyevent
2)伪随机事件流信息
当 Monkey 开始执行测试后,会顺序输出执行的事件流信息,主要是前面提到的 11 大事件。这部分日志信息的解析,如代码清单 4-4 所示。
代码清单 4-4 Monkey 日志 - 伪随机事件流信息
//执行的事件流信息
//启动 App 事件
:Switch: #Intent; action=android.intent.action.MAIN; category=android.intent.
category.LAUNCHER; launchFlags=0x10200000; component=com.tencent.android.
qqdownloader/com.tencent.assistant.activity.SplashActivity; end
// Allowing start of Intent { act=android.intent.action.MAIN cat=[android.
intent.category.LAUNCHER] cmp=com.tencent.android.qqdownloader/com.tencent.
assistant.activity.SplashActivity } in packagecom.tencent.android.qqdownloader
//轨迹球事件
:Sending Trackball (ACTION_MOVE): 0:(4.0,2.0)
//点击事件
:Sending Touch (ACTION_DOWN): 0:(387.0,1858.0)
:Sending Touch (ACTION_UP): 0:(385.8215,1861.3011)
//延时
Sleeping for 0 milliseconds
…
3)异常信息
当 Monkey 执行过程中遇到错误时,会输出对应异常信息,如代码清单 4-5 所示。
代码清单 4-5 Monkey 日志 - 异常信息
//发送 Crash 的应用包名和 pid
// CRASH: com.tencent.android.qqdownloader (pid 912)
//Crash 的简要信息
// Short Msg: java.lang.ClassNotFoundException
//Crash 的详细信息
// Long Msg: java.lang.ClassNotFoundException: Didn't find class "com.
qq.AppService.AstApp" on path DexPathList[[zip file "/data/app/com.tencent.
android.qqdownloader-2.apk"], nativeLibraryDirectories[/data/app-lib/com.
tencent.android.qqdownloader-2, /vendor/lib, /system/lib]]
//机型和系统信息
// Build Label: Xiaomi/pisces/pisces:4.4.4/KTU84P/5.12.24:user/release-keys
// Build Changelist: 5.12.24
// Build Time: 1450958964000
//Crash 的详细日志
// java.lang.RuntimeException: Unable to instantiate application com.
qq.AppService.AstApp: java.lan.ClassNotFoundException: Didn't find class "com.
qq.AppService.AstApp" on path: DexPathList[[zip fil "/data/app/com.tencent.
android.qqdownloader-2.apk"], nativeLibraryDirectories=[/data/app-lib/com.
tecent.android.qqdownloader-2, /vendor/lib, /system/lib]]
// at android.app.LoadedApk.makeApplication(LoadedApk.java:509)
// at android.app.ActivityThread.access$1500(ActivityThread.java:138)
// at dalvik.system.NativeStart.main(Native Method)
// ... 11 more
//
4)Monkey 执行结果信息
当 Monkey 执行完所有事件后,会输出执行结果信息,其中包括执行的事件数量、旋转的角度、丢失的事件数量、网络状态以及 Monkey 最终的执行结果,如代码清单 4-6 所示。
代码清单 4-6 Monkey 日志 - 执行成功结果信息
//执行的事件数量
Events injected: 10
//旋转的角度为 0
:Sending rotation degree=0, persist=false
//丢失的事件数量
:Dropped: keys=0 pointers=0 trackballs=0 flips=0 rotations=0
//网络状态,移动网络联网 0ms, Wi-Fi 联网 0ms,没联网 144ms
Network stats: elapsed time=144ms (0ms mobile, 0ms wifi, 144ms not connected)
// Monkey finished
如果 Monkey 执行过程中出现了异常导致执行失败,会输出对应的执行失败的原因,第几个事件执行失败以及所使用的随机种子数,如代码清单 4-7 所示。
代码清单 4-7 Monkey 日志 - 执行失败结果信息
//显示 Monkey 执行失败
** Monkey aborted due to error.
//执行的事件数量
Events injected: 8
//旋转的角度为 0
:Sending rotation degree=0, persist=false
//丢失的事件数量
:Dropped: keys=0 pointers=0 trackballs=0 flips=0 rotations=0
//网络状态
Network stats: elapsed time=405ms (0ms mobile, 0ms wifi, 405ms not connected)
//提示在执行到第 8 个事件时出现 Crash,以及所使用的随机种子的值
** System appears to have crashed at event 8 of 100 using seed 1454216848235
3.Monkey 日志异常信息查找
Monkey 执行过程中常见的错误类型主要有两类:应用程序无响应(ANR)和崩溃(Crash)。
(1)ANR 是指当 Android 系统监测到应用程序在 5 秒内没有响应输入的事件或广播在 10 秒内没有执行完毕时抛出无响应提示。当出现 ANR 时弹出的错误提示框如图 4-9 所示。ANR 弹窗
(2)Crash 是指当应用程序出现错误时导致程序异常停止或退出的情况,当出现 Crash 时通常会弹出对应的错误提示框如图 4-10 所示。crash 弹窗
表 4-7 常见 Crash 信息表
(3)其他问题:在日志中搜索” Exception” 和 “ERROR"等信息,再具体分析出错的情况及相应的日志输出。
作为测试同学,尤其是测试开发,或是高级测试开发及以上等级的同学,执行一下 Monkey 测试,再分析一下测试结果,是不是显得有点儿 Low 呢?完全体现不出我们的设计理念及代码水平嘛!那如何才能将 Monkey 测试做的高大上呢?
1,前期数据准备
并不是所有的 app 直接执行一下 monkey 命令,分析一下测试结果就行;如新浪微博,今日头条这类信息流展示类的 app,直接连接电脑,执行 Monkey 测试没有问题。可是如 QQ,金融类的 App,打开的时候就要求我们登录,此时如果直接执行 Monkey 测试,那只能操作到登录界面,后面的业务逻辑相关的页面根本操作不到的。所以为了更好地进行测试,我们需要先登录被测试 App,切到测试环境,构造业务相关的数据,如添加 QQ 好友,发 QQ 信息等,然后在此基础上执行 monkey 测试,才会更加真实;而这些操作,可以借助于 App 自动化测试框架 Appium 来实现。
2,Money 配置化执行
Monkey 执行的时候参数非常多,每次输入命令非常不方便。所以我们可以封装 Monkey 执行参数,将其中需要变化的参数,如执行次数,要测试的 App PageName 等参数化,根据不同的执行需要,通过参数的形式传递过来即可。而此类问题,可以通过 Python,Java,Shell 等进行封装,定制化执行即可。当然可以对要测试的 App 的信息进行智能化分析,自动识别执行,从而使代码更加灵活。
3,测试结果的智能分析
要知道执行的结果,我们需要采取上面的方法分析执行日志;但是如果执行的次数过多,执行的频繁的话,日志分析也是很大的工作量。所以我们可以对日志执行的结果进行智能分析,在执行 Monkey 测试的时候,把执行手机的型号,系统信息以及其他必要的信息写入日志,然后对过 shell 命令对日志进行分析。自动过滤与统计出错误信息的数量 ,出错的日志信息等,分别写入错误统计文件或是数据库中,以备后续生成测试报告或是图形化展示执行结果做数据准备。
4,自动生成测试报告
清晰明了的测试报告是提高测试效率的重要手段,如果执行结束后能很快明确执行结果,测试效率必然很高。这就要求我们在执行完 monkey 测试后,通过对日志的智能分析,自动生成测试报告,测试报告中需要包括这次执行的环境信息,执行结果的汇总信息,以及对出错信息的展示。所以可能借助于 Html+Css+js 来生成的我们的测试报告,将测试结果的智能分析数据,灵活地展现出来。
通过对上面的四个功能的分析,我们可以对 Monkey 测试做一个整体设计,设计出合适的代码架构对上面的功能进行整体的封装和数据串联;实现如下流程所示:
经过合适的代码实现,即能完成一个有一定设计理念,具备智能分析能力的 Monkey 测试项目。后续如果有需求,可以在兼容性,相关业务的关联上进行扩展,从而形成 App 性能测试平台或是生态。这是我最近在做 Monkey 测试的一些思考,分享给大家,希望能给你带来点不一样的思考!