Monkey

Monkey

官方文档

Monkey 是运行在你的模拟器或者设备上一个程序,它能产生伪随机事件,如用户点击,触摸,用户手势(译者:gestures 指用户的连续动作导致屏幕的动态显示,Android 上可以使用手指“拉动”屏幕的效果就是 gesture), 以及一系列的系统级事件。你可以使用 Monkey 对你的程序进行压力测试,它可随机产生一些重复的东西。

1. 概述

Monkey 是一个命令行程序,你可以跑在模拟器或者设备上。它发送随机的用户和系统事件,可以对你开发的应用程序进行压力测试。

Monkey 包含一系列的选项,但可以分解为 4 个主要的类别:

  1. 基本设置选项,例如设置一些事件。
  2. 操作限制,如限制测试某一个单独的包。
  3. 事件类型以及频率。
  4. 调试选项。

当 Monkey 运行时,它产生的事件被发送给系统。它会监视正在测试系统并寻找三种情况做特殊处理:

  1. 如果你限制 Monkey 在一个或者多个包里运行,如果发现程序试图使用其它包,就对其进行阻塞。
  2. 如果你的程序崩溃或者收到任何无法处理的异常, Monkey 就会停止并且报告错误。
  3. 如果你的程序产生一个程序没有答复的错误, Monkey 会停止并报告错误。

根据选项的冗长程度,你可以看到 Monkey 运行时候产生的报告,这个时候事件已经开始产生。

2. Monkey 的基本用法

你可以通过命令或者脚本启动 Monkey 。因为 Monkey 运行在模拟器 / 设备里。你需要在这些环境的 shell 里启动它,使用时,在每个命令前加上 adb shell。

基本语法:

adb shell monkey [options] <event-count>
Bash Copy

没有选项指定时, Monkey 安静(没有其它复杂内容)模式启动,然后发送事件给所有安装在你目标扳上的包里。

这里有一个有代表性的命令,它能启动你的程序并发送 500 个随机的事件给程序。

adb shell monkey -p io.github.liushilive.at -v 500
Bash Copy

3. Monkey 压力测试实践

  1. 在手机 开发者选项 中,选中 USB 调试
  2. 确认手机与电脑连接: adb devices
  3. 安装测试 APP: adb install package.apk
  4. 获取 APP 包名:进入 Shell adb shell ,筛选日志输出 logcat | grep Displayed or adb logcat | findstr START
  5. 给指定包打压力: adb shell monkey -vvv --throttle 500 -p io.github.liushilive.at 1000 > monkey.txt 2>&1
  6. 分析日志

    1. 程序无响应的情况:搜索关键字 ANR
      1. 进入 adb shell: adb shell
      2. 进入 anr 目录: cd data/anr
      3. 查看 traces.txt
      4. 提取 traces.txt 文件: adb pull /data/anr/traces.txt
    2. 崩溃、闪退的情况 1:搜索关键字 CRASH
    3. 崩溃、闪退的情况 2:搜索关键字 Exception
    4. 内存溢出的情况:搜索关键字 OOM
    5. 测试成功的情况:搜索关键字 Monkey finished
  7. 重现: adb shell monkey -p io.github.liushilive.at -vvv -s 1546458727792 1000 > monkey1.txt 2>&1

  • 加随机数种子: adb shell monkey -vvv -p com.android.calculator2 -s 100 50
  • 加延迟: adb shell monkey -vvv -p com.android.calculator2 --throttle 1000 10
  • 触摸事件: adb shell monkey -vvv -p com.android.calculator2 --pct-touch 100 100

4. 日志解析

adb shell monkey -vvv -p io.github.liushilive.at --pct-touch 1 --pct-motion 2 --pct-pinchzoom 3 --pct-trackball 4 --pct-rotation 5 --pct-permission 6 --pct-nav 7 --pct-majornav 8 --pct-syskeys 9 --pct-appswitch 10 --pct-flip 11 --pct-anyevent 34 --throttle 100 100 > 1.txt 2>&1
Bash Copy

4.1. 各事件的百分比

  • --pct-touch 0:触摸事件百分比(触摸事件是一个在屏幕单一位置的按下 - 抬起事件)
  • --pct-motion 1:手势事件(手势事件是由一个在屏幕某处的按下事件、一系列的伪随机移动、一个抬起事件组成)即一个滑动操作,但是是直线的,不能拐弯
  • --pct-pinchzoom 2:二指缩放事件,放大缩小手势操作
  • --pct-trackball 3:轨迹事件
  • --pct-rotation 4:屏幕旋转事件
  • --pct-permission 5: 权限许可事件
  • --pct-nav 6:基本导航事件
  • --pct-majornav 7:主要导航事件
  • --pct-syskeys 8:系统按键事件
  • --pct-appswitch 9:启动 Activity 事件
  • --pct-flip 10:键盘事件
  • --pct-anyevent 11:其他类型事件
#随机种子数,执行事件数量
:Monkey: seed=1545952923355 count=100
#运行的应用列表
:AllowPackage: io.github.liushilive.at
#Category包含:LAUNCHER与MONKEY
:IncludeCategory: android.intent.category.LAUNCHER
:IncludeCategory: android.intent.category.MONKEY
#各事件的百分比
// Event percentages:
//   0: 1.0%
//   1: 2.0%
//   2: 3.0%
//   3: 4.0%
//   4: 5.0%
//   5: 6.0%
//   6: 7.0%
//   7: 8.0%
//   8: 9.0%
//   9: 10.0%
//   10: 11.0%
//   11: 34.0%
#执行的事件流信息
#启动APP事件
:Switch: #Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=cc.liushi.testapp/.HomeScreenActivity;end
    // Allowing start of Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=cc.liushi.testapp/.HomeScreenActivity } in package cc.liushi.testapp
#点击事件
:Sending Touch (ACTION_DOWN): 0:(698.0,306.0)
:Sending Touch (ACTION_UP): 0:(703.8239,325.90808)
....
:Sending Touch (ACTION_UP): 0:(1184.9438,428.81464)
:Sending Trackball (ACTION_MOVE): 0:(4.0,0.0)
# 异常信息
// CRASH: cc.liushi.testapp (pid 2901)
// Short Msg: java.lang.ArithmeticException
// Long Msg: java.lang.ArithmeticException: divide by zero
# 机型和系统信息
// Build Label: Android/sdk_phone_x86/generic_x86:7.0/NYC/4174735:userdebug/test-keys
// Build Changelist: 4174735
// Build Time: 1499888857000
# crash详细信息
// java.lang.ArithmeticException: divide by zero
//     at android.widget.SimpleMonthView.findClosestColumn(SimpleMonthView.java:550)
# Monkey执行结果信息
** Monkey aborted due to error.
Events injected: 437
:Sending rotation degree=0, persist=false
:Dropped: keys=1 pointers=0 trackballs=0 flips=0 rotations=0
## Network stats: elapsed time=9984ms (0ms mobile, 0ms wifi, 9984ms not connected)
** System appears to have crashed at event 437 of 1000 using seed 1515393057075
Bash Copy

5. Android 平台 Monkey 测试标准

  • 系统稳定性测试

    • 测试样机数量:5-10 台

    • 运行时间:25 小时

    • 测试要求:

      1) 运行时间》20 小时

      2) 样机运行时间按从小到大排序,取中间 2 个值,计算平均时间,要求时间中间值平均为 24 小时

      3) 以上两个条件均满足则认为通过测试(运 行过程中无异常)

  • 单个 APK 运行稳定性测试

    • 测试样机数量:5-10 台

    • 运行时间:25 小时

    • 测试要求:

      平均运行时间至少为 20 小时(>380000 个 ENVENT), 测试过程中无 ANR、 JAVACRASH、NativeCrash、WindowLeak、 Exceeds VM budget count 等任何异常

6. 猴运行业内标准

最终发布前,Monkey 跑完的总次数应为 25W 次,其结果里不允许有 nullPointException 出现。

7. 命令选项参考

下面的表格里列出了所有包含在 Monkey 命令行的参数:

类别

选项

描述

通用

--help

打印使用向导。

-v

每个 -v 在命令里都会增加日志级别,0 级别(默认)在启动、测试结束、最终结果之外只提供很少的信息,1 级别在运行时提供更详细的测试信息,例如每个发往你活动的事件。 2 级别提供更加详细的设置信息,如一个活动是否选中被测试。

事件

-s <seed>

随机数字产生器的种子。如果你用同样的种子运行 Monkey ,它将会产生相同的事件。

--throttle <milliseconds>

在事件中插入一个固定的延迟。一般使用这个命令去延缓 Monkey 程序。如果没有指定, Monkey 产生的事件将没有延迟并尽可能快的发送。

--pct-touch <percent>

调整触摸事件的比例。(触摸事件是一个在屏幕上单点按下的事件)

--pct-motion <percent>

调整手势事件的比例。(手势事件由一系列屏幕上的按下事件组成,一系列的伪随机移动和一个松开事件)

--pct-trackball <percent>

调整跟踪球事件(跟踪球由一个或多个随机移动事件组成,有时还会接一个单击事件)

--pct-nav <percent>

调整”基本”导航事件。(导航事件由上 / 下 / 左 / 右组成,这些事件由输入设备输入)

--pct-majornav <percent>

调整“主要”的导航事件的比例。(有些导航事件将会在你的 UI 里导致一些动作,例如在 5 向键里的中间,退出键,或者菜单键)

--pct-syskeys <percent>

调整“系统”事件的比例。(有些键通常是系统保留的,如 主界面,退出,电话,结束通话,或者声音调节 )

--pct-appswitch <percent>

调整活动被运行的比例。 在一些随机的间隔里, Monkey 会调用一个 startActivity()的调用,以最大程序得覆盖你包里的所有的活动。

--pct-anyevent <percent>

调整其他类型事件的比例。 这包含所有其他的事件,如用户按键,其他设备上不常用的的按键,等等。

限制

-p <allowed-package-name>

如果你指定一个或者多个包, Monkey 程序仅仅允许系统访问这些包里的活动。如果你的应用程序需要进入其他包的活动(例如选择一个联系人),你也需要指定这个包。如果你不指定任何包, Monkey 将允许系统运行所有包里活动。

指定多个包,可以多次使用 -p 选项 —— 一个—每个 p 选项选一个包。

-c <main-category>

如果你指定一个或多个类别(category), Monkey 将仅仅允许系统访问这些指定类别里的一个活动。如果你不指定任何类别, Monkey 将选择 Intel.CATEGORY _LAUNCHER 或者 CATEGORY_MONKEY 列出的活动。如果要选择多个类别,多次使用 -c 选项 —— 每个 -c 选一个类别。

调试

--dbg-no-events

当被指定时, Monkey 将在测试活动里执行初始化运行程序,但还没有产生任何事件。 最好的是集成 -v, 能使一个或多个包被限制,这样一个非 0 的控制能保证 Monkey 程序运行 30 秒或更长时间。这提供一个环境,你可以监视你的应用程序调用的包的所有变化。

--hprof

如果设置这个选项,系统会在 Monkey 事件序列前后都立即产生程序分析报告。这将会产生巨大的(~5M)数据文件,所以请谨慎使用。

--ignore-crashes

通常情况下, Monkey 会因为程序崩溃或者遇到一些无法处理的异常而停止,但你指定了这个选项, Monkey 会继续发事件给系统,直到事件计数器结束。

--ignore-timeouts

通常情况下, Monkey 会因为程序超时而停止,例如程序弹出“应用程序没有答复”的对话框。如果你指定了这个选项, Monkey 会继续发事件给系统,直到事件计数器结束。

--ignore-security-exceptions

通常情况下, Monkey 会因为一些权限错误而停止,例如,它试图运行一个需要特殊权限的活动。 如果指定这个选项, Monkey 会继续发送事件给系统,直到事件计数器结束。

--kill-process-after-error

通常情况下, Monkey 会因为错误停止,应用程序失败但会并停留在运行状态,当这个条件设置后,它会发消息给系统在错误发生的地方停止进程。 评注:在程序正常(成功)的完成,运行的程序不会停止,设备会收到结束事件而停留在最后的状态上。

--monitor-native-crashes

监视并报告 Android 系统代码里的崩溃事件。如果设置了 --kill-process-after-error, 系统将会停止。

--wait-dbg

停止 Monkey 直到调试工具连接上程序。

上一篇:在 Ali Kubernetes 系统中,我们这样实践混沌工程


下一篇:移动端测试---adb 命令与monkey命令