Monkey日志分析是Monkey測試中非常重要的一個環節,通過日志分析,可以獲取當前測試對象在測試過程中是否會發生異常,以及發生的概率,同時還可以獲取對應的錯誤信息,幫助開發定位和解決問題。介紹日志分析方法之前,先來看一下日志的保存方法。
1.Monkey日志的保存方法
Monkey運行日志常見的保存方法有三種:
❑ 保存在PC中,代碼如下:
>adb shell monkey [option] <count> >d:\monkey.txt
執行以上命令,Monkey的運行日志將被保存在PC上的D盤下的一個monkey.txt文件中。
❑ 保存在手機中,代碼如下:
>adb shell
>monkey [option] <count> > /mnt/sdcard/monkey.txt
執行以上命令,Monkey的運行日志將被保存在手機中的SD卡上的一個monkey.txt文件中。
❑ 標注流與錯誤流分開保存,代碼如下:
Monkey [option] <count> 1>/sdcard/monkey.txt 2>/sdcard/error.txt
執行以上命令,Monkey的運行日志和異常日志將被分開保存。此時Monkey的運行日志將被保存在monkey.txt文件中,而異常日志將被保存在D盤下的error.txt中。
執行結束后,可以看到SD卡上新增加了monkey.txt和error.txt。monkey.txt顯示運行日志,如圖4-7所示。
[插圖]
圖4-7 運行日志輸出
如果Monkey執行期間存在Crash(崩潰)或ANR(Application Not Responding,應用程序無響應), error.txt中會顯示錯誤日志,如圖4-8所示。
[插圖]
圖4-8 異常日志輸出
2.Monkey日志內容解析
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)。
ANR是指當Android系統監測到應用程序在5秒內沒有響應輸入的事件或廣播在10秒內沒有執行完畢時拋出無響應提示。當出現ANR時彈出的錯誤提示框如圖4-9所示。ANR彈窗

Crash是指當應用程序出現錯誤時導致程序異常停止或退出的情況,當出現Crash時通常會彈出對應的錯誤提示框如圖4-10所示。crash彈窗

要統計Monkey日志中錯誤出現的次數也非常簡單,只要搜索關鍵字“ANR”和“CRASH”出現的次數即可。由於通常Monkey測試的日志會比較大,日志內容也非常多,為了簡化統計操作,可以使用bat腳本進行統計,具體如代碼清單4-8所示。
代碼清單4-8 Monkey日志分析bat腳本
@echo off&setlocal enabledelayedexpansion
#設置所有Monkey日志存放的目錄
set ff=log\*.txt
#設置查詢關鍵字
set str=CRASH crash ANR died
#設置查詢結果存放的目錄
set fileName=Result.txt
#開始查詢
echo 正在統計&echo;
echo %date% %time% >%fileName%
echo.>>%fileName%
echo 分析結果:>>%fileName%
echo ---------------------------------------------->>%fileName%
#依次打開目錄下每一個Monkey日志查詢關鍵字並輸出個數
(for %%a in (%str%)do (
set n%%a=0&set/p= %%a : <nul>con
for /f "delims=" %%b in ('findstr "%%a" "%ff%"')do (
set h=%%b
call :yky %%a)
echo ! n%%a! >con
echo 關鍵字 %%a 共有 ! n%%a! 處
))>>%fileName%
echo.>>%fileName%
#針對崩潰的日志輸出其所在文件行數
echo 崩潰日志:>>%fileName%
findstr "%str%" "%ff%">>%fileName%
echo/&pause&exit
:yky
set/a n%1+=1
set h=! h:*%1=!
if defined h if not "! h:*%1=! "=="! h! " goto :yky
最終執行后,在腳本目錄下會生成Result.txt文件記錄異常出現的次數,如圖4-11所示。

圖4-11 日志分析結果文件
根據統計結果,可以得到Crash和ANR出現的次數,以及出現在哪個日志文件中,出現該錯誤的包名。如果需要更詳細的錯誤信息,可以打開對應的Monkey日志文件查詢。通過詳細日志信息,測試可以定位到引起Crash的原因,以及出現Crash的代碼行信息。這里給出常見的一些Crash錯誤信息,見表4-7。
表4-7 常見Crash信息表

當獲取到Crash和ANR日志信息后,理論上開發人員就可以開始根據日志內容分析和定位問題了。但事實上,要定位問題單靠日志信息還是非常困難的,有時候開發人員還需要知道問題復現的場景,同時增加更多的調試日志以協助定位。這時候,他們可能會期望測試能夠復現問題或者提供問題出現場景和操作步驟。通常,測試人員可以通過使用同一個種子數(seed值),再次執行Monkey來嘗試復現問題。這種方法比較費時,並且不是所有的隨機Crash和ANR都可以通過這種方法來復現。那問題來了,在Monkey出現問題的時候有沒有可能即時地截圖並且記錄下操作步驟呢?Monkey本身是沒有這個能力的,但是通過一些Monkey改造可以實現該功能。