二、将以上脚本复制到一个文本文件中,命名为xx.bat
三、对脚本文件进行二次编辑
- 获取包名:①aapt dump badging [XXaaayy.apk],例如:package: name='com.jddl.rbr'②只记得大概,不记得详细包名。例如adb shell pm list packages b2
- 修改命令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 > "%monkeyLogFile%"中的包名,如:com.jddl.rbr
- 修改monkey执行次数:-v -v -v ,这个代表执行次点击。
- 保存,连接手机,打开手机开发调试模式
- Monkey命令停止:cmd命令下输入adb shell 进入命名模式,执行命令ps | grep monkey 查看进程ID,kill +进程ID,杀掉进程
四、命令简解
执行伪随机事件的总操作次数
-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 <percent>,此时所有事件的触发均为随机的。当所有事件的百分比加起重来小于100%的时候,多余的随机事件也将被转化为--pct-anyevent <percent>事件。超过时,系统会重新运算相应的比例
-s 伪随机数生成器的seed值。monkey允许对随机事件的seed值做设置,当两次seed值一样,整个测试效果将会产生相同的事件序列。例如:monkey -pcom.tencent.mtaexample -s 23 --throttle2000 --ignore-crashes --ignore-timeouts -v -v -v >/data/local/tmp/log.txt 2>&1 &(其中-s后面是对应的种子数,好像就是操作步骤,根据她们测试的经验,一般种子数在23,同步她们测试的结果,一般种子的个数固定为23,和她们选择的操作步骤就是同步的。2>&1 固定的写法,这个也很重要,代表的意思是中间忽略的东东的日志一并输入到指定的文件中。最后单独的一个"&" 是一旦Monkey测试开始了,之后可以拔掉数据线,不会影响Monkey测试。)
执行adb shell --help,查看帮助
五、日志分析
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=0x;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=ms (0ms mobile, ms 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=0x;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:
// 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值,在以后的调试中会经常需要查询:
摘录另一种日志分析: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
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=0x;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链接来生成报告。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/7040.html