Android Monkey压力测试使用

时间:2023-01-13 17:43:33

 

 

 

 

 

一、Monkey简介:

Monkey是Android中的一个命令行工具,可以运行在模拟器里或者现实设备中,向系统发送伪随机的用户事件流(点击、滑动、Application切换、横竖屏、应用关闭)实现对正在开发的应用程序进行压力测试。monkey测试是一种为了测试软件的稳定性,健壮性的快速有效的方法。只针对Activity做测试,不能对Service做测试。

简单的理解:

Monkey 是一个 Android 自动化测试小工具。主要用于Android 的压力测试, 主要目的就是为了测试app 是否会Crash.

Monkey测试,就像一只猴子, 在电脑面前,乱敲键盘在测试。 猴子什么都不懂, 只知道乱敲。通过Monkey程序模拟用户触摸屏幕、滑动Trackball、 按键等操作来对设备上的程序进行压力测试,检测程序多久的时间会发生异常。

二、质量要求:

版本release(发布)前,Monkey跑出来的结果中crash要为0,final release前,Monkey跑完的总次数应为25W,结果里不允许有nullPointException出现。

三、使用Monkey:

在cmd命令或者AndroidStudio中的Terminal中都可以使用adb(注意adb的位置,在SDK的tools文件夹下)

  1、首先需要将手机连接到PC,测试连接是否正常,找到adb的位置,一般在sdk的tools文件下 ,找到位置然后输入adb devices来进行验证;

  2、因测试多针对一个特定的APP包,所以需要知道需要测试包的包名;可以直接问开发,也可以通过 adb shell pm list packages  列出所有包名来进行查找

  (不确定包是否已安装,可以用adb shell pm list packages [options] <INTENT> 来进行确认,它的含义是列举出所有包含<INTENT>的package。    e.g. adb shell pm list packages com.taobao.taobao)

  3、对特定APP包进行测试的命令为adb shell monkey -p <pakage.name>

三、Monkey的基本参数:

1、允许启动手机里面所有的 App , 随机操作 1000 次

adb shell monkey 1000

2、-p : 允许启动 App 的包名

  • 启动一个包名的应用

QQ 的包名为: com.tencent.mobileqq

adb shell monkey -p com.tencent.mobileqq 1000

随机操作 手机 QQ 1000 次

  • 启动指定的多个 App

微信的包名为:com.tencent.mm

adb shell monkey -p com.tencent.mobileqq -p com.tencent.mm 1000

随机操作 手机 QQ 和 微信 1000 次

3、-v : 操作日志记录

命令行的每一个-v将增加反馈信息的级别。

  • -v:Level 0(缺省值)除 启动提示、测试完成和最终结果之外,提供较少信息。
  • -v -v :Level 1提供较为详细的测试信息,如逐个发送到Activity的 事件。
  • -v -v -v :Level 2提供更加详细的设置信息,如测试中被选中的或未被选中的Activity。

adb shell monkey -p com.tencent.mobileqq -v -v -v 100

4、-s : 伪随机数生成器的seed值

如果用相同的seed值再次运行monkey,将生成相同的事件序列。

adb shell monkey -s 12345 -v 10

5、--ignore-crashes : 忽略操作是崩溃异常

通常,应用发生崩溃或异常时Monkey会停止运行。如果设置此项,Monkey将继续发送事件给系统,直到事件计数完成。

adb shell monkey --ignore-crashes -v 1000

6、--ignore-timeouts : 忽略超时

通常,应用程序发生任何超时错误(如“Application Not responding”对话框)Monkey将停止运行,设置此项,Monkey将继续发送事件给系统,直到事件计数完成。

adb shell monkey --ignore-timeouts -v 1000

7、--ignore-security-exceptions : 忽略程序发生许可异常

通常,当程序发生许可错误(例如启动一些需要许可的Activity)导致的异常时,Monkey将停止运行。设置此项,Monkey将继续发送事件给系统,直到事件计数完成。

adb shell monkey --ignore-security-exceptions -v 1000

8、--throttle : 插入固定延迟

在事件之间插入固定延迟。通过这个选项可以减缓Monkey的执行速度。如果不指定该选项,Monkey将不会被延迟,事件将尽可能快地被执行。

adb shell monkey --throttle 500 -v 500

随机执行 500 个事件,每个事件之间延迟 500 毫秒被执行。

9、--help : 列出简单的用法

adb shell monkey -help

 

四、将log日志文件保存到指定位置:

  android studio 的terminal 下执行命令并且将测试结果保存到指定文件下:


             adb shell monkey -p 包名 -s 100 --ignore-crashes --ignore-timeouts  1000000 >C:\Users\dingchao\Desktop\testlog.txt

 

五、日志分析:

1)正常情况:顺利执行完成, 在log的最后, 会打印出当前执行事件的次数和所花费的时间; // Monkey finished 代表执行完成\

详细分析参考:

http://blog.sina.com.cn/s/blog_44d19b500102vefp.html

http://blog.csdn.net/huangyabin001/article/details/38442359


Android Monkey压力测试使用

Android Monkey压力测试使用

Android Monkey压力测试使用

Android Monkey压力测试使用

Android Monkey压力测试使用

Android Monkey压力测试使用

2)异常情况:

 Android Monkey压力测试使用

Android Monkey压力测试使用

Android Monkey压力测试使用

其中adb shell procrank 查询各进程内存使用情况;adb shell cat /proc/meminfo 查看当前的内存情况...

 Android Monkey压力测试使用

Monkey 测试出现错误后,一般的分析步骤
看Monkey的日志 (为了进一步分析问题的来源,可以找到Log中出现问题处的前一次Switch,随后根据Log主要是查看相关的Activity)
1、程序无响应的问题:在日志中搜索 “ANR”

可能原因:当前有耗时操作在UI线程指定,导致卡UI了;在5秒内没有响应输入的事件(例如,按键按下,屏幕触摸);BroadcastReceiver在10秒内没有执行完毕

2、崩溃问题:在日志中搜索 “Exception”   (如果出现空指针, NullPointerException)  肯定是有bug
3、搜索"crash" 、"error"

 Monkey 执行中断, 在log最后也能看到当前执行次数;若以上步骤还不能定位问题,可以使用之前执行的monkey命令再执行一遍,注意seed值要一样



可能出现Crash的场景

1)图片放大缩小

2)输入框无限输入各种类型字符

3)快速操作

4)和系统的交互等等

Android Monkey压力测试使用

 

 

什么时候会有Log文件的产生 ?
Log的产生大家都知道 , 大家也都知道通过DDMS来看log , 但什么时候会产生log文件呢 ?一般在如下几种情况会产生log文件 。 
1,程序异常退出 , uncaused exception
2,程序强制关闭 ,Force Closed (简称FC)
3,程序无响应 , Application No Response (简称ANR) , 顺便,一般主线程超过5秒么有处理就会ANR
4,手动生成 。


拿到一个日志文件,要分成多段来看 。 log文件很长,其中包含十几个小单元信息,但不要被吓到 ,事实上他主要由三大块儿组成 。

1,系统基本信息 ,包括 内存,CPU ,进程队列 ,虚拟内存 , 垃圾回收等信息 。------ MEMORY INFO (/proc/meminfo) ------
------ CPU INFO (top -n 1 -d 1 -m 30 -t) ------
------ PROCRANK (procrank) ------
------ VIRTUAL MEMORY STATS (/proc/vmstat) ------
------ VMALLOC INFO (/proc/vmallocinfo) ------

格式如下:
------ MEMORY INFO (/proc/meminfo) ------
MemTotal:         347076 kB
MemFree:           56408 kB
Buffers:            7192 kB
Cached:           104064 kB
SwapCached:            0 kB
Active:           192592 kB
Inactive:          40548 kB
Active(anon):     129040 kB
Inactive(anon):     1104 kB
Active(file):      63552 kB
Inactive(file):    39444 kB
Unevictable:        7112 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                44 kB
Writeback:             0 kB
AnonPages:        129028 kB
Mapped:            73728 kB
Shmem:              1148 kB
Slab:              13072 kB
SReclaimable:       4564 kB
SUnreclaim:         8508 kB
KernelStack:        3472 kB
PageTables:        12172 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      173536 kB
Committed_AS:    7394524 kB
VmallocTotal:     319488 kB
VmallocUsed:       90752 kB
VmallocChunk:     181252 kB


2,时间信息 , 也是我们主要分析的信息 。
------ VMALLOC INFO (/proc/vmallocinfo) ------
------ EVENT INFO (/proc/vmallocinfo) ------

格式如下:
------ SYSTEM LOG (logcat -b system -v time -d *:v) ------
01-15 16:41:43.671 W/PackageManager( 2466): Unknown permission com.wsomacp.permission.PROVIDER in package com.android.mms
01-15 16:41:43.671 I/ActivityManager( 2466): Force stopping package com.android.mms uid=10092
01-15 16:41:43.675 I/UsageStats( 2466): Something wrong here, didn't expect com.sec.android.app.twlauncher to be paused
01-15 16:41:44.108 I/ActivityManager( 2466): Start proc com.sec.android.widgetapp.infoalarm for service com.sec.android.widgetapp.infoalarm/.engine.DataService: pid=20634 uid=10005 gids={3003, 1015, 3002}
01-15 16:41:44.175 W/ActivityManager( 2466): Activity pause timeout for HistoryRecord{48589868 com.sec.android.app.twlauncher/.Launcher}
01-15 16:41:50.864 I/KeyInputQueue( 2466): Input event
01-15 16:41:50.866 D/KeyInputQueue( 2466): screenCaptureKeyFlag setting 0
01-15 16:41:50.882 I/PowerManagerService( 2466): Ulight 0->7|0
01-15 16:41:50.882 I/PowerManagerService( 2466): Setting target 2: cur=0.0 target=70 delta=4.6666665 nominalCurrentValue=0
01-15 16:41:50.882 I/PowerManagerService( 2466): Scheduling light animator!
01-15 16:41:51.706 D/PowerManagerService( 2466): enableLightSensor true
01-15 16:41:51.929 I/KeyInputQueue( 2466): Input event
01-15 16:41:51.933 W/WindowManager( 2466): No focus window, dropping: KeyEvent{action=0 code=26 repeat=0 meta=0 scancode=26 mFlags=9}



3,虚拟机信息 , 包括进程的,线程的跟踪信息,这是用来跟踪进程和线程具体点的好地方 。 
------ VM TRACES JUST NOW (/data/anr/traces.txt.bugreport: 2011-01-15 16:49:02) ------
------ VM TRACES AT LAST ANR (/data/anr/traces.txt: 2011-01-15 16:49:02) ------


格式如下 :
----- pid 21161 at 2011-01-15 16:49:01 -----
Cmd line: com.android.mms

DALVIK THREADS:
"main" prio=5 tid=1 NATIVE
  | group="main" sCount=1 dsCount=0 s=N obj=0x4001d8d0 self=0xccc8
  | sysTid=21161 nice=0 sched=0/0 cgrp=default handle=-1345017808
  | schedstat=( 4151552996 5342265329 10995 )
  at android.media.MediaPlayer._reset(Native Method)
  at android.media.MediaPlayer.reset(MediaPlayer.java:1218)
  at android.widget.VideoView.release(VideoView.java:499)
  at android.widget.VideoView.access$2100(VideoView.java:50)
  at android.widget.VideoView$6.surfaceDestroyed(VideoView.java:489)
  at android.view.SurfaceView.reportSurfaceDestroyed(SurfaceView.java:572)
  at android.view.SurfaceView.updateWindow(SurfaceView.java:476)
  at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:206)
  at android.view.View.dispatchDetachedFromWindow(View.java:6082)
  at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:1156)
  at android.view.ViewGroup.removeAllViewsInLayout(ViewGroup.java:2296)
  at android.view.ViewGroup.removeAllViews(ViewGroup.java:2254)
  at com.android.mms.ui.SlideView.reset(SlideView.java:687)
  at com.android.mms.ui.SlideshowPresenter.presentSlide(SlideshowPresenter.java:189)
  at com.android.mms.ui.SlideshowPresenter$3.run(SlideshowPresenter.java:531)
  at android.os.Handler.handleCallback(Handler.java:587)
  at android.os.Handler.dispatchMessage(Handler.java:92)
  at android.os.Looper.loop(Looper.java:123)
  at android.app.ActivityThread.main(ActivityThread.java:4627)
  at java.lang.reflect.Method.invokeNative(Native Method)
  at java.lang.reflect.Method.invoke(Method.java:521)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
  at dalvik.system.NativeStart.main(Native Method)

---------------------------------------------------------------------------------------------------------------------------------------
闲话少说, 我总结了观察log文件的基本步骤 。 1,如果是ANR问题 , 则搜索“ANR”关键词 。 快速定位到关键事件信息 。
2,如果是ForceClosed 和其它异常退出信息,则搜索"Fatal" 关键词, 快速定位到关键事件信息 。
3,定位到关键事件信息后 , 如果信息不够明确的,再去搜索应用程序包的虚拟机信息 ,查看具体的进程和线程跟踪的日志,来定位到代码 。 

用这种方法,出现问题,根本不需要断点调试 , 直接定位到问题,屡试不爽 。 
下面,我们就开始来分析这个例子的log 。

打开log文件 , 由于是ANR错误,因此搜索"ANR " , 为何要加空格呢,你加上和去掉比较一下就知道了 。 可以屏蔽掉不少保存到anr.log文件的无效信息 。

 

 

 

关闭Monkey

在monkey运行中,断开USB连接,mokey仍可继续运行
1. ps命令查找进程
adb shell ps | grep monkey  返回来的第一个数字,即是monkey的进程号
2.kill 命令结束进程
adb shell kill [刚才查到的进程号]