1. 程式人生 > >Android測試工具Monkey用法簡介

Android測試工具Monkey用法簡介

Monkey是Android中的一個命令列工具,可以執行在模擬器裡或實際裝置中。它向系統傳送偽隨機的使用者事件流(如按鍵輸入、觸控式螢幕輸入、手勢輸入等),實現對正在開發的應用程式進行壓力測試。Monkey測試是一種為了測試軟體的穩定性、健壯性的快速有效的方法。

Monkey測試引數建議

  • 間隔時間:500毫秒;
  • 種子數:隨機;
  • 遇到錯誤:不停止
  • 執行時長:每機型不小於12小時 或 點選次數:100萬次;
  • 機型覆蓋建議:覆蓋高中低端機型,不同晶片平臺,不同解析度,不同安卓版本;
  • 參考命令:
    adb shell monkey -p com.package.xxx --throttle 500 --ignore-crashes --ignore-timeouts --ignore-security-exceptions --ignore-native-crashes --monitor-native-crashes -v -v -v 1000000>G:\MonkeyTest.log 2>&1 &

Monkey測試方案

  • 單一apk測試:
    monkey –p <options> -c <options> -s <seed> <限制語句> --throttle <milliseconds> -v 執行次數> G:\MonkeyTest.log

  • 集合apk測試:

    • 黑名單以外的APK:
      monkey –pkg-blacklist-file /data/local/tmp/blacklist.txt -c <options> -s <seed> <限制語句> --throttle <milliseconds> -v 執行次數>G:\MonkeyTest.log

    • 白名單中APK:
      monkey –pkg-whitelist-file /data/local/tmp/whitelist.txt -c <options> -s <seed> <限制語句> --throttle <milliseconds> -v 執行次數 > G:\MonkeyTest.log

Monkey測試指令碼

Android 的 monkey test 工具提供了 -f scriptfile 引數,可以指定 test 指令碼

  • 什麼是monkey script
    Monkey script是按照一定的語法規則編寫有序的使用者事件流並適用於monkey命令工具的指令碼
    adb shell monkey -f <script file> <執行指令碼的次數>

    • 例:adb shell monkey -f /sdcard/monkey.script 10,那麼這個腳本里面指定的動作就會被執行10次
      說明:指令碼位置可以是絕對位置,也可以是相對位置(cd進入相應的目錄
  • development/cmds/monkey/src/com/android/commands/monkey/MonkeySourceScript.java原始碼下有一段註釋規定了monkey script的基本規則:

    monkey event queue. It takes a script to produce events 
    sample script format: 
         type= raw events 
         count= 10 
         speed= 1.0 
         start data >> 
         captureDispatchPointer(5109520,5109520,0, 
          230.75429,458.1814,0.20784314,0.06666667 
               ,0,0.0,0.0,65539,0)
         captureDispatchKey(5113146,5113146,0,20,0,0,0,0) 
         captureDispatchFlip(true) 
          ... 
    */  
  • 指令碼的內容示例(原始碼修正版)

    //header
    type= raw events
    count= 10
    speed= 1.0
    //line at the end of the header means that below it is the context of script
    start data >>
    DispatchPointer(5109520,5109520,0,230.75429,458.1814,0.20784314,
    0.06666667,0,0.0,0.0,65539,0)
    DispatchKey(5113146,5113146,0,20,0,0,0,0)
    DispatchFlip(true)
    ...

    說明:
    1)、前3行是指令碼頭
    2)、後3行是指令碼內容,每行為一個函式

  • monkey中提供的函式如下:

    1..DispatchPointer(long downTime,  long eventTime, int action, float x, float y, float pressure, float size, int metaState, float xPrecision, float yPrecision, int device, int edgeFlags)  
    2..DispatchTrackball(long downTime,  long eventTime, int action,  float x, float y, float pressure, float size, int metaState,  float xPrecision, float yPrecision, int device, int edgeFlags)    軌跡球
    3..DispatchKey(long downTime, long eventTime, int action, int code, int repeat, int metaState, int device, int scancode)     
    4..DispatchFlip(boolean keyboardOpen)    實體鍵盤關閉與開啟
    5..DispatchPress(int keyCode)    
    6..LaunchActivity(String pkg_name, String cl_name)  
    7..UserWait(long sleeptime)    
    8..LongPress(int keyCode)
    • 鍵盤按下/彈起
      key [down|up] keycode
      這個命令模擬一次鍵盤輸入。
      keycode引數值詳見KeyEvent類的KEYCODE列表。這個引數的格式很靈活,例如模擬選單按鈕可以使用82(選單按鈕的鍵值),也可以使用 KEYCODE_MENU(鍵值的名稱,必須嚴格都是大寫字母),還可以使用menu(Monkey程式會自動新增KEYCODE部分,此時並不區分大小 寫)。
      注意一次完整的敲擊(press)操作是一個按下(key down)和彈起(key up)的組合
    • 觸控按下/彈起/移動
      touch [down|up|move] x y
      This command injects a MotionEvent into the input system that simulates a user touching the touchscreen (or a pointer event). x and y specify coordinates on the display (0 0 being the upper left) for the touch event to happen. Just like key events, touch events at a single location require both a down and an up. To simulate dragging, send a “touch down”, then a series of “touch move” events (to simulate the drag), followed by a “touch up” at the final location.
    • 滾動軌跡球
      trackball dx dy
      This command injects a MotionEvent into the input system that simulates a user using the trackball. dx and dy indicates the amount of change in the trackball location (as opposed to exact coordinates that the touch events use)
    • 開啟/關閉實體鍵盤
      flip [open|close]
      模擬一次實體鍵盤的開啟/關閉。
      在沒有實體鍵盤的手機上此命令無效。
    • 喚醒裝置(點亮螢幕)
      wake
      這個命令將喚醒裝置,並允許使用者輸入。
      如果裝置鍵盤已鎖,這個命令並不能解鎖鍵盤
    • 螢幕點選
      tap x y
      這個命令模擬一次螢幕點選。
      這個命令就是touch down和touch up命令的一次組合。
    • 敲擊鍵盤
      press keycode
      這個命令模擬一次鍵盤敲擊。
      這個命令就是key down和key up命令的一次組合。
    • 鍵入字串
      type string
      這個命令模擬鍵入一個字串
      該命令會完全模擬每一個字元的鍵盤事件
      列出環境變數
    • listvar
      該命令將列出Monkey的所有環境變數。
      返回值為空格分隔的字串。
    • 獲取環境變數值
      getvar varname
      該命令用於獲取指定的環境變數的值。
      通過listvar命令獲取支援的環境變數列表。
    • 退出Monkey
      quit
      完全退出Monkey
      Monkey不再接受新的連線。
    • 結束當前會話
      done
      結束當前會話。
      Monkey還可以接受新的連線。
    • 休眠
      sleep ms
      使Monkey進入休眠一段時間,引數為整數,單位毫秒
    • 註釋
      #
      以#開頭的語句會被Monkey當做註釋。傳送這樣的命令Monkey不會返回錯誤也不會返回OK。
  • 常用函式介紹
    以下列表提煉於原始碼MonkeySourceScript.java
    DispatchKey(downTime,eventTime,action,code,repeat,metaState,device,scancode)
    @param long downTime //鍵最初被按下的時間
    @param long eventTime //事件發生的時間
    @param int action //(ACTION_DOWN=0,ACTION_UP=1,ACTION_MULTIPLE=2)
    @param int code //鍵值,比如KEYCODE_DPAD_DOWN(20)
    @param int repeat //
    @param int metaState //當前按下的meta鍵的標識
    @param int device //事件發生的裝置id
    @param int scancode //
    DispatchPointer(downTime, eventTime,action, x, y, pressure, size, metaState, xPrecision,yPrecision,device, edgeFlags)
    @param long downTime //鍵最初被按下的時間
    @param long eventTime //事件發生的時間
    @param int action //(ACTION_DOWN=0,ACTION_MOVE=1,ACTION_UP=2,ACTION_CANCEL=3)
    @param float x //x座標
    @param float y //y座標
    @param float pressure //當前事件的壓力,範圍0-1
    @param float size //觸控的近似值,範圍0-1
    @param int metaState //當前按下的meta鍵的標識
    @param float xPrecision //x座標精確值
    @param float yPrecision //y座標精確值
    @param int device //事件來源,範圍0-x,0表示不來自物理裝置
    @param int sedgeFlags //
    DispatchTrackball(downTime, eventTime,action, x, y, pressure, size, metaState, xPrecision,yPrecision,device, edgeFlags)
    Tap(x,y,duration);
    DispatchPress(String key_name)
    DispatchFlip(boolean keyboardOpen)
    UserWait(long sleeptime)
    LaunchActivity(String pkg_name, String cl_name,long alarmTime)
    UserWait(long sleeptime)
    LongPress()

示例:

  • Start Script
    type = user
    count = 49
    speed = 1.0
    start data >>
    LaunchActivity(com.android.browser,com.android.browser.BrowserActivity)
    UserWait(5000)

    #back to home
    captureDispatchPointer(5109520,5109520,0,1150,330,0,0,0,0,0,0,0);
    captureDispatchPointer(5109521,5109521,1,1150,330,0,0,0,0,0,0,0);
    UserWait(3000)

    #close browser
    captureDispatchPointer(5109520,5109520,0,205,31,0,0,0,0,0,0,0);
    captureDispatchPointer(5109521,5109521,1,205,31,0,0,0,0,0,0,0);
    UserWait(2000)

    以上是一個示例指令碼。
    具體的操作步驟為:
    1. 將上述指令碼複製到script.txt中
    2. 將script.txt放到sd卡根目錄
    3. adb shell monkey –v –v –v –f /sdcard/script.txt –throttle 1500 100 > monkey.txt
      指令碼會按照script.txt傳送的指令序列每隔1.5s執行一個指令,執行100遍,並將log存在monkey.txt檔案中

Monkey測試結果分析

  • Android平臺應用程式可能產生以下四種Crash:

    • App層:
      1、Force Close Crash
      2、ANR Crash
    • Native層:
      3、Tombstone Crash(Native Crash)
    • Kernel層:
      4、Kernel Panic
  • 主要Monkey日誌

    • anr目錄:從手機/data/anr匯出的日誌,儲存發生anr crash 時的相關資訊;
    • dontpanic目錄:從手機/data/dontpanic/匯出的日誌,儲存發生Kernel Panic時的相關資訊;
    • Tombstone目錄:從手機/data/tombstones/匯出的日誌,儲存發生Tombstone Crash時的錯誤資訊;
    • dropbox目錄:從手機/data/system/dropbox/匯出的日誌,經過dropbox服務擷取的部分tombstones錯誤資訊;
    • BugReportLog.log:通過adb shell bugreport命令提取的系統各種資訊;
    • MonkeyTest.Log:儲存Monkey測試過程、應用層錯誤資訊,發生Native Crash時,在此檔案也會有記錄;
  • 一般的測試結果分析:
    Monkey測試出現錯誤後,一般的差錯步驟為以下幾步:

    • 找到是monkey裡面的哪個地方出錯
    • 檢視Monkey裡面出錯前的一些事件動作,並手動執行該動作
    • 若以上步驟還不能找出,可以使用之前執行的monkey命令再執行一遍,注意seed值要一樣
    • 在MonkeyTest.Log日誌檔案搜尋關鍵詞“Fatal”、“Crash”、“ANR”定位到發生Crash的詳細堆疊資訊,或分析發生Crash前後的日誌事件;
    • 檢查dropbox目錄下是否有相關crash日誌資訊,主要關注是否有以下4類crash錯誤資訊:
      data_app_wtfdata_app_anrdata_app_crashsystem_server_watchdog
    • 檢查tombstone目錄是否有生成日誌,有的話說明發生過native crash
    • 通過anr目錄中的日誌檔案或BugReport.log日誌檔案,進一步分析問題原因;

Monkey測試的延伸

monkey工具不能實現指定模組測試,以下記錄兩種實現指定模組測試的方法

方法1:
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
from random import randint
print("get device")
device = MonkeyRunner.waitForConnection()
package = 'com.swl.a1vod'
activity = 'org.coolx.videoframework.vod.VodDetailsActivity'
runComponent = package + '/' + activity
device.startActivity(component=runComponent)

#use commands like device.touch and device.drag to simulate a navigation and open my activity
#with your activity opened start your monkey test
print("start monkey test")
for i in range(1, 1000):
#here i go emulate only simple touchs, but i can emulate swiper keyevents and more... :D
device.touch(randint(0, 1000), randint(0, 800), 'DOWN_AND_UP')
print("end monkey test")

#執行monkeyrunner G:\script\monkeytest.py

方法2:

<activity android:name="MonkeyActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.MONKEY" />
</intent-filter>
</activity>

adb shell monkey -p my.package -c android.intent.category.MONKEY -v 500