最全的monkey测试过程及分析

一、首先第一步安装Android SDK,完成后。编写测试脚本,我的脚本已经编写好。具体大家可以从网上Google针对自己的情况再进行详细的编改。

@ECHO OFF
 
ECHO.:::::::::::::::::::::::::::::::::::::::::::::::::
 
ECHO.::             分析Monkey日志                  ::
 
ECHO.::             版本:V1.0.0                   ::
 
ECHO.::             部门:新通路                   ::
 
ECHO.::             脚本编写:宋小宝                ::
 
ECHO.::             异常处理:王宝强                 ::
 
ECHO.:::::::::::::::::::::::::::::::::::::::::::::::::
 
REM 设置Monkey日志路径 
SET monkeyLogFile=%cd%\%date:~0,4%%date:~5,2%%date:~8,2%%time:~0,2%%time:~3,2%.txt
 
REM 方法二:直接将Monkey日志拖到此bat文件上
IF NOT "%1"=="" (
 
	SET monkeyLogFile=%1
 
) ELSE (
	ECHO.[ INFO ] Monkey执行中...
	REM Monkey执行命令
	adb shell monkey -p com.jd.b2r --throttle 500 --ignore-crashes --ignore-timeouts --ignore-security-exceptions --ignore-native-crashes --monitor-native-crashes -v -v -v 30000 > "%monkeyLogFile%"
 
)
 
 
ECHO.[ INFO ] Monkey日志: %monkeyLogFile%
 
ECHO.[ INFO ] 开始分析
 
SET blnException=0
 
ECHO.
 
ECHO.
 
REM 如果觉得分析太快,没有感觉,把下面注释去掉假装分析中,有停顿感
 
ping -n 2 127.0.0.1>nul
  
 
::ANR日志
 
FOR /F "delims=" %%a IN ('FINDSTR /C:"ANR" %monkeyLogFile%') DO (
 
    SET strANR=%%a
 
)
 
 
::崩溃日志
 
FOR /F "delims=" %%a IN ('FINDSTR /C:"CRASH" %monkeyLogFile%') DO (
 
    SET strCRASH=%%a
 
)
   
 
::异常日志
 
FOR /F "delims=" %%a IN ('FINDSTR /C:"Exception" %monkeyLogFile%') DO (
 
    SET strException=%%a
 
)
  
 
::正常
 
FOR /F "delims=" %%a IN ('FINDSTR /C:"Monkey finished" %monkeyLogFile%') DO (
 
    SET strFinished=%%a
 
)
  
 
IF NOT "%strANR%" == "" (
 
    ECHO.[ INFO ] 分析Monkey日志存在: ANR
 
    ECHO.[ INFO ] ------------------------------------
 
    ECHO.         "%strANR%"
 
    SET /a blnException+=1
 
    ECHO.
 
)
 
 
IF NOT "%strCRASH%" == "" (
 
    ECHO.[ INFO ] 分析Monkey日志存在: CRASH
 
    ECHO.[ INFO ] ------------------------------------
 
    ECHO.         "%strCRASH%"
 
    SET /a blnException+=1
 
    ECHO.
 
)
 
 
IF NOT "%strException%" == "" (
 
    ECHO.[ INFO ] 分析Monkey日志存在: 异常
 
    ECHO.[ INFO ] ------------------------------------
 
    ECHO.         "%strException%"
 
    SET /a blnException+=1
 
)
  
 
IF NOT "%strFinished%" == "" (
 
    ECHO.[ INFO ] 分析Monkey日志存在: 执行成功标记
 
    ECHO.[ INFO ] ------------------------------------
 
    ECHO.         "%strFinished%"
 
    ECHO.
 
) ELSE (
 
    IF %blnException% EQU 0 ECHO.[ INFO ] 分析Monkey日志结果: Monkey执行异常中断,请重新执行Monkey脚本!
 
    ECHO.
 
)
  
 
REM 如果blnException不为0,说明存在异常,改变字体为淡紫色
 
IF %blnException% NEQ 0 (
 
    Color 0D
 
    ECHO.[ INFO ] 分析Monkey日志结果:存在异常日志,请手工再仔细检查!
 
    ECHO.
 
) ELSE (
 
    ECHO.[ INFO ] 分析Monkey日志结果:正常
 
    ECHO.
 
)
 
ECHO.
 
ECHO.[ EXIT ] 按任意键关闭窗口...
 
PAUSE>nul

二、将以上脚本复制到一个文本文件中,命名为xx.bat

三、对脚本文件进行二次编辑

  1. 获取包名:①aapt dump badging [XXaaayy.apk],例如:package: name='com.jddl.rbr'②只记得大概,不记得详细包名。例如adb shell pm list packages b2
  2. 修改命令adb shell monkey -p com.jddl.rbr --throttle 500 --ignore-crashes --ignore-timeouts --ignore-security-exceptions --ignore-native-crashes --monitor-native-crashes -v -v -v 100000 > "%monkeyLogFile%"中的包名,如:com.jddl.rbr
  3. 修改monkey执行次数:-v -v -v 100000,这个100000代表执行100000次点击。
  4. 保存,连接手机,打开手机开发调试模式
  5. Monkey命令停止:cmd命令下输入adb shell 进入命名模式,执行命令ps | grep monkey  查看进程ID,kill +进程ID,杀掉进程 

四、命令简解

100000 执行伪随机事件的总操作次数

-p com.jddl.rbr 指定包名,如果未指定,如:adb shell monkey 1000。将命令随机发送到手机中的所有APP,随机执行1000个次事件

--throttle 500 单位毫秒。每执行一系列操作事件,停顿休息500ms

-v 日志级别。最高为三个,-v -v -v为打印输出最详细的日志,自己可以修改查看具体效果

--ignore-crashes 忽略崩溃/--ignore-timeouts 忽略超时/--ignore-security-exceptions 忽略安全异常。APP在操作过程中会存在崩溃、超时、异常等情况,导致monkey直接停止测试。忽略这些异常崩溃可继续执行,直到执行随机时间次数达到设定值。当不作任何配置的时候,默认为--pct-anyevent ,此时所有事件的触发均为随机的。当所有事件的百分比加起重来小于100%的时候,多余的随机事件也将被转化为--pct-anyevent 事件。超过时,系统会重新运算相应的比例

-s 伪随机数生成器的seed值。monkey允许对随机事件的seed值做设置,当两次seed值一样,整个测试效果将会产生相同的事件序列。例如:monkey -pcom.tencent.mtaexample -s 23  --throttle2000 --ignore-crashes --ignore-timeouts -v -v -v 100000>/data/local/tmp/log.txt 2>&1 &(其中-s后面是对应的种子数,好像就是操作步骤,根据她们测试的经验,一般种子数在23,同步她们测试的结果,一般种子的个数固定为23,和她们选择的操作步骤就是同步的。2>&1 固定的写法,这个也很重要,代表的意思是中间忽略的东东的日志一并输入到指定的文件中。最后单独的一个"&" 是一旦Monkey测试开始了,之后可以拔掉数据线,不会影响Monkey测试。)

  * --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>:指定任意事件的百分比。

执行adb shell --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

五、日志分析

Monkey测试结果分析

一. 初步分析方法:

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

1、找到是monkey里面的哪个地方出错

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

3、若以上步骤还不能找出,可以使用之前执行的monkey命令再执行一遍,注意seed值要一样--复现

一般的测试结果分析:

1、 ANR问题:在日志中搜索“ANR”

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

二. 详细分析monkey日志:

将执行Monkey生成的log,从手机中导出并打开查看该log;在log的最开始都会显示Monkey执行的seed值、执行次数和测试的包名。

首先我们需要查看Monkey测试中是否出现了ANR或者异常,具体方法如上述。

然后我们要分析log中的具体信息,方法如下:

查看log中第一个Switch,主要是查看Monkey执行的是那一个Activity,譬如下面的log中,执行的是com.tencent.smtt.SplashActivity,在下一个swtich之间的,如果出现了崩溃或其他异常,可以在该Activity中查找问题的所在。

:Switch:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10000000;component=com.tencent.smtt/.SplashActivity;end

  // Allowing start of Intent {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]cmp=com.tencent.smtt/.SplashActivity } in package com.tencent.smtt

在下面的log中,Sending Pointer ACTION_DOWN和Sending Pointer ACTION_UP代表当前执行了一个单击的操作;

Sleeping for 500 milliseconds这句log是执行Monkey测试时,throttle设定的间隔时间,每出现一次,就代表一个事件。

SendKey(ACTION_DOWN) //KEYCODE_DPAD_DOWN 代表当前执行了一个点击下导航键的操作;

Sending Pointer ACTION_MOVE 代表当前执行了一个滑动界面的操作。
:Sending Pointer ACTION_DOWN x=47.0 y=438.0
:Sending Pointer ACTION_MOVE x=-2.0 y=-4.0
ANR
如果Monkey测试顺利执行完成,在log的最后,会打印出当前执行事件的次数和所花费的时间;// Monkey finished代表执行完成。Monkey执行中断,在log的最后也能查看到当前已执行的次数。Monkey执行完成的log具体如下:

Events injected: 6000

:Dropped: keys=0 pointers=9 trackballs=0 flips=0

## Network stats: elapsed time=808384ms (0ms mobile, 808384ms wifi, 0msnot connected)

// Monkey finished

范例:

Monkey测试结果:

# monkey -p wfh.LessonTable -v -v -v 200

:Monkey: seed=0 count=200

:AllowPackage: wfh.LessonTable

:IncludeCategory: android.intent.category.LAUNCHER

:IncludeCategory: android.intent.category.MONKEY

// Selecting main activities from category android.intent.category.LAUNCHER

//   - NOT USING main activity com.android.browser.BrowserActivity (from package com.android.browser)

// Seeded: 0

// Event percentages:

//   0: 15.0%  --事件0 为touch事件,就是相当于按下之后弹起来的一个动作
//   1: 10.0%  --事件1 为motion,相当于说从起始点到终点有移动了多少步,就是步骤数量 
//   2: 2.0%   --事件2 为pinchzoom,为两个手指有同时按下去后,都向中间移动后up起来,相当于一个缩放的动作。
//   3: 15.0%  --事件3 为trackball,为轨迹球事件 
//   4: -0.0%  --事件4 为rotation 为屏幕旋转百分比隐藏事件
//   5: 25.0%  --事件5 为nav导航事件,就是上下左右
//   6: 15.0%  --事件6 为majornav主导航事件,会产生一些窗口的事件
//   7: 2.0%   --事件7 为系统按键
//   8: 2.0%   --事件8,app应用的打开就是用的这个事件
//   9: 1.0%   --事件9,键盘的开,关

//   10: 13.0% --事件10,按键按下在弹起等动作

:Switch: #Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10000000;component=wfh.LessonTable/.MainTable;end

    // Allowing start of Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=wfh.LessonTable/.MainTable } in package wfh.LessonTable

Sleeping for 0 milliseconds

:SendKey (ACTION_DOWN): 21    // KEYCODE_DPAD_LEFT

:SendKey (ACTION_UP): 21    // KEYCODE_DPAD_LEFT

Sleeping for 0 milliseconds  //------------------------------------用--throttle来设置一个起效的事件发生后时延时。

:Sending Pointer ACTION_DOWN x=0.0 y=0.0

:Sending Pointer ACTION_UP x=0.0 y=0.0

Sleeping for 0 milliseconds

:Sending Pointer ACTION_MOVE x=0.0 y=0.0

当测试到ACTION_MOVE x=0.0 y=0.0这个动作时,发生了FC(Force Close)错误,以下为输出错误信息。同时在LogCat里面也有错误输出,而且LogCat里面的错误信息更为详细,在实际的测试中应该结合两者输出的信息进行调试程序。

// CRASH: wfh.LessonTable (pid 1973)

// Short Msg: java.lang.NullPointerException

// Long Msg: java.lang.NullPointerException

// Build Label: android:generic/sdk/generic/:2.1-update1/ECLAIR/35983:eng/test-keys

// Build Changelist: 35983

// Build Time: 1273161972

// ID:

// Tag: AndroidRuntime

// java.lang.NullPointerException:

//   at android.widget.TabHost.dispatchKeyEvent(TabHost.java:279)

//   at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:748)

** Monkey aborted due to error.

Events injected: 190

:Dropped: keys=0 pointers=11 trackballs=0 flips=0

## Network stats: elapsed time=27954ms (27954ms mobile, 0ms wifi, 0ms not connected)

** System appears to have crashed at event 190 of 200 using seed 0

#

开始monkey测试时android的LogCat输出的信息:

11-01 08:52:53.712: DEBUG/AndroidRuntime(2077): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<

11-01 08:52:53.742: DEBUG/AndroidRuntime(2077): CheckJNI is ON

11-01 08:52:54.453: DEBUG/AndroidRuntime(2077): ---

以下为LogCat输出的错误信息,在以下的信息中首先从自己的包中找错误,如果没有自己的包的话就再找发生错误的包的第一个发生了异常。由错误提示可以看出很大的可能是因为TabHost引发的异常。经过查看代码发现是由于TabHost的编写不规范,TabHost与其中一个view放在了一起,在monkey测试做滚球上下滚动时当滚到TabHost时就发生了异常了。所以把TabHost与Activity分开写就不会出现些问题了。

11-01 08:53:27.113: ERROR/AndroidRuntime(1973): Uncaught handler: thread main exiting due to uncaught exception

11-01 08:53:27.133: ERROR/AndroidRuntime(1973): java.lang.NullPointerException

11-01 08:53:27.133: ERROR/AndroidRuntime(1973):     at android.widget.TabHost.dispatchKeyEvent(TabHost.java:279)

11-01 08:53:27.133: ERROR/AndroidRuntime(1973):     at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:748)

六、附录:

以下内容为android系统中的keycode值,在以后的调试中会经常需要查询:

字母和数字键的键码值(keyCode)

按键

键码

按键

键码

按键

键码

按键

键码

A

65

J

74

S

83

1

49

B

66

K

75

T

84

2

50

C

67

L

76

U

85

3

51

D

68

M

77

V

86

4

52

E

69

N

78

W

87

5

53

F

70

O

79

X

88

6

54

G

71

P

80

Y

89

7

55

H

72

Q

81

Z

90

8

56

I

73

R

82

0

48

9

57

数字键盘上的键的键码值(keyCode)

功能键键码值(keyCode)

按键

键码

按键

键码

按键

键码

按键

键码

0

96

8

104

F1

112

F7

118

1

97

9

105

F2

113

F8

119

2

98

*

106

F3

114

F9

120

3

99

+

107

F4

115

F10

121

4

100

Enter

108

F5

116

F11

122

5

101

-

109

F6

117

F12

123

6

102

.

110

 

 

 

 

7

103

/

111

 

 

 

 

控制键键码值(keyCode)

按键

键码

按键

键码

按键

键码

按键

键码

BackSpace

8

Esc

27

Right Arrow

39

-_

189

Tab

9

Spacebar

32

Dw Arrow

40

.>

190

Clear

12

Page Up

33

Insert

45

/?

191

Enter

13

Page Down

34

Delete

46

`~

192

Shift

16

End

35

Num Lock

144

[{

219

Control

17

Home

36

;:

186

\|

220

Alt

18

Left Arrow

37

=+

187

]}

221

Cape Lock

20

Up Arrow

38

,<

188

'"

222

多媒体键码值(keyCode)

按键

键码

按键

键码

按键

键码

按键

键码

音量加

175

 

 

 

 

 

 

音量减

174

 

 

 

 

 

 

停止

179

 

 

 

 

 

 

静音

173

 

 

 

 

 

 

浏览器

172

 

 

 

 

 

 

邮件

180

 

 

 

 

 

 

搜索

170

 

 

 

 

 

 

收藏

171

 

 

 

 

 

 

摘录另一种日志分析:https://www.cnblogs.com/kekouwen/p/9995635.html 

1.在日志中搜索关键字:

1)搜索报告中的关键字“ANR”,看有无应用无响应的事件(Application Not Responding)

2)搜索报告中的关键字“crash”,看有无崩溃的事件

3)搜索报告中的关键字“exception”,看有无其他异常事件。(如果出现空指针, NullPointerException,需格外重视)

下面的属于monkey自己的问题。不用管。

:Sending Flip keyboardOpen=false

Got IOException performing flipjava.io.IOException: write failed: EINVAL (Invalid argument)

// Injection Failed

4)内存泄露问题搜索"GC"(需进一步分析)

2. 初步分析法: monkey出现错误后,一般的分析步骤

1)先找到出现错误的位置

2)查看出现错误之前2个switch之间的activity

3)手动执行事件,复现问题

4)若以上步骤还不能找出,产生错误时,有会seed值,输入相同的seed值,重新按照之前命令跑monkey

3.详细分析法:
1) ANR问题:在日志中搜索“ANR”(“Application Not Responding"),说明有bug,出现ANR,一般是主线程的响应超过5秒,或者BroadcastReceiver没有在10秒内作出响应。这个就是一个比较严重的缺陷。把耗时的操作另起线程来处理就可以了。

2)分析log中的具体信息:

查看log中第一个Switch,主要是查看Monkey执行的是那一个Activity,譬如下面的log中,执行的是com.tencent.smtt.SplashActivity,在下一个swtich之间的,如果出现了崩溃或其他异常,可以在该Activity中查找问题的所在。

:Switch:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10000000;component=com.tencent.smtt/.SplashActivity;end

  // Allowing start of Intent {act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER]cmp=com.tencent.smtt/.SplashActivity } in package com.tencent.smtt

3)内存泄漏

1. 内存泄漏弹出out of memory对话框
2. 对于有内存泄漏但是没有单出out of memory对话框的情况,可以通过logcat文件GC出信息,(GC:java的垃圾回收机制)
GC_FOR_ALLOC: 因为在分配内存时候内存不够引起的
GC_EXPLICIT 表明GC被显式请求触发的,如System.gc调用,
GC_CONCCURRENT: 表明GC在内存使用率达到一定的警戒值时候,自动触发
GC_BEFORE_OOM 表明在虚拟机抛出内存不够异常oom之前,执行最后一次回收内存垃圾

2.发现内存泄露--内存报告分析(利用hprof参数的内存快照生成内存报告)

在发现内存泄露后,可以执行相同的monkey,只需多加一个参数--hprof 

adb shell monkey -p 包名  --hprof --throttle 100  --pct-touch 50 --pct-motion 50 -v -v -v 1000 >c:\monkey.txt

如果指定了这个选项,monkey会在发送时间的前后生成app内存快照文件,一般会在手机设备的/data/misc目录下生成hprof的文件。(注:  /data/misc  需要root权限,可

以在手机上安装个RE查看或通过手机助手查看)

ps:文件转换:配置monkey测试时的sdk-tools下查看是否hprof-conv命令,在命令行输入hprof-conv -help得知文件转化用法,直接转化就行,由.hprof转化成.conv格式。

转化后的文件用eclipse的Memory Analyzer tool(MAT)查看(此插件可以下载),可以点击 Reports->Leak Suspects链接来生成报告。

你可能感兴趣的:(工具)