Android自動化測試入門(一)Monkey和MonkeyRunner

測試是應用開發中不可或缺的一部分。測試所做的工作,雖然不能讓用戶看到效果,但是想要保證一個有一定用戶基礎的應用的穩定性,測試是必須做的,否則嚴重的崩潰率肯定會導致用戶的差評或者流失。

ADB工具使用

ADB的使用Android開發者應該都很熟悉了,它是電腦和手機之間連接的一個橋樑。電腦端有一個Client和一個Server,Client負責輸入命令,Server負責和手機連接,手機端通過adbd跟Server交互

常用的ADB命令

  • adb devices 列出電腦連接的設備 和 設備id,設備狀態

  • adb push 電腦端推送文件到手機 比如 adb -s 設備名 push 1.jpg /data/temp/1.jpg 如果連接了一個設備可以不用自定設備名稱

  • adb pull 從手機拉取文件到電腦 比如 adb -s 設備名 pull /data/temp/1.jpg /data/11.jpg

  • adb forward 端口轉發 比如 adb forward tcp:11111 tcp:22222的意思是,將PC端的11111端口收到的數據,轉發給到手機中22222端口

  • adb start-server/adb kill-server 啓動/殺死ADB服務

  • adb install/adb uninstall 安裝/卸載 apk uninstall命令需要指定應用的包名

  • adb shell 可以在電腦上直接進入手機終端界面操作手機

進入adb shell之後 使用 pm list packages 可以列出手機上是所有包名

android命令可以用來查看當前Android開發環境中的系統信息和操作。主要有

  • android sdk查看sdk
  • android avd模擬器相關,
  • android list列表 比如android list target列出所支持的Android平臺,android list avd列出所有的模擬器
  • android create project創建一個Android工程。

把sdk/tools路徑配置到環境變量中或者直接進入sdk/tools目錄中執行這些命令即可。

Monkey 工具

Monkey是Andorid系統中自帶的一個黑盒測試工具,可以產生僞隨機事件(點擊、輕觸)流。一般是通過隨機觸發界面事件,來確定是否發生了異常。一般用於Android應用的穩定性、壓力測試

簡單使用

Monkey是一個命令行工具,可以在任何模擬器或者設備上運行,將僞隨機事件流發送到系統中來進行壓力測試。 需要通過adb shell來啓動,命令格式

adb shell monkey [option] <event-count>

各種參數的作用官網上有詳細文檔:官網地址

下面進入adb shell中做一個小例子:

通過pm list packages命令可以看到手機中所有的包名,可以隨便找一個測試,這裏使用系統計算器來測試它的包名是com.android.calculator2

可以執行下面的命令,來執隨機行應用1000次

monkey -p com.android.calculator2 1000

可以通過-v 來輸出執行日誌,比如

monkey -p com.android.calculator2 -v -v 100

-v的個數表示日誌輸出的級別,最多三個,越多日誌越詳細來看看輸出的日誌

data="com.android.calculator2"
//使用monkdy工具 測試了100次
//通過-s指定seed的值可以重複跟本次操作一模一樣的操作
:Monkey: seed=1582553186510 count=100 
//測試的包名
:AllowPackage: com.android.calculator2 
//策略
:IncludeCategory: android.intent.category.LAUNCHER
:IncludeCategory: android.intent.category.MONKEY
// Selecting main activities from category android.intent.category.LAUNCHER
//   + Using main activity com.android.calculator2.Calculator (from package com.android.calculator2)
// Selecting main activities from category android.intent.category.MONKEY
// Seeded: 1582553186510
// Event percentages:
//每一種事件測試的佔比,每個數組代表不同的事件類型
//
//   0: 15.0%
//   1: 10.0%
//   2: 2.0%
//   3: 15.0%
//   4: -0.0%
//   5: -0.0%
//   6: 25.0%
//   7: 15.0%
//   8: 2.0%
//   9: 2.0%
//   10: 1.0%
//   11: 13.0%

.....
//網絡狀況 執行時間
## Network stats: elapsed time=484ms (0ms mobile, 0ms wifi, 484ms not connected)
// Monkey finished

日誌最開始有個輸出seed=1582553186510,通過這個值我們可以重新執行一次一模一樣的當前操作adb shell monkey -s 1487572980979 -v 1000

1-11的佔比代表各種事件的執行比例,比如輕觸事件,手勢事件,縮放事件,導航事件,屏幕旋轉事件等在MonkeySourceRandom這個類中有常量表示。下面是Android 9.0源碼中的數值常量。

    public static final int FACTOR_TOUCH        = 0; //輕觸
    public static final int FACTOR_MOTION       = 1; //滑動
    public static final int FACTOR_PINCHZOOM    = 2; //縮放
    public static final int FACTOR_TRACKBALL    = 3; //軌跡球
    public static final int FACTOR_ROTATION     = 4; //旋轉
    public static final int FACTOR_PERMISSION   = 5; //權限
    public static final int FACTOR_NAV          = 6; //基本導航  上下左右鍵等
    public static final int FACTOR_MAJORNAV     = 7; //主要導航(一般會導致UI變化)  回退鍵 菜單鍵等
    public static final int FACTOR_SYSOPS       = 8; //系統事件
    public static final int FACTOR_APPSWITCH    = 9; //activity啓動事件
    public static final int FACTOR_FLIP         = 10; //鍵盤翻轉
    public static final int FACTOR_ANYTHING     = 11; //其他事件

如果執行過程中發生了崩潰,Monkey會停在崩潰的地方,使用--ignore-crashes可以在崩潰的時候繼續執行後序操作adb shell monkey —ignore-crashes 1000

程序ANR對於andorid應用來說是一個比較嚴重的問題,Monkey在執行中遇到ANR的時候會停止,執定--ignore-timeouts參數可以讓monkey繼續執行adb shell monkey --ignore-timeouts 1000

使用>符號將日誌輸出到特定的文件中查看比如adb shell monkey —ignore-crashes 1000>d:\monkey.txt,此文件中會告訴我們那個地方出了問題,具體的錯誤日誌可以通過adb bugreport命令將運行日誌導出來查看更詳細的信息

//6.0及以下設備
adb bugreport > bugreport.txt
//7.0及以上設備
adb bugreport bugreport.zip

Monkey 腳本

有時候我們不想讓它隨機執行,通過腳本可以讓測試按照我們自定義的流程來執行。使用-f參數就可以執行Monkey的腳本了adb shell monkey -f <script> 1

官網沒有介紹Monkey腳本的使用的文章,可以參照sdk源碼中的寫法。在MonkeySourceScript.java這個類中可以參考。

Monkey腳本的主要命令:

  • DispatchPointer(downtime,eventTime,action,x,y,xpressure,size,metastate,xPrecision,yPrecision,device,edgeFlags):手勢操作,相當於手指按到某個位置。參數x,y是手指按下的座標位置,座標位置可以通過DDMS中的工具UI Automator來獲取,位置在sdk/tools/monitor中
  • DispatchPress[keycode] 按下系統的某個固定的按鍵,比如home鍵,back鍵等,在官網KeyEvent這個類中有對每種keycode含義的詳細介紹。
  • LaunchActivity(pkg_name, cl_name): 用來啓動應用 參數是 包名+類名
  • UserWait:讓腳本暫停一段時間
  • UserWait(sleepTime):指定睡眠時間
  • RotateScreen(rotationDegree, persist):參數是旋轉角度+旋轉後是否停在當前位置。0代表0度 1代表90度 2代表180度 3代表 270度;第二個參數 0表示旋轉後恢復,非0則表示固定不變
  • Tap(x, y,tapDuration):單擊時間 x y 是點擊屏幕的座標 點擊的時長
  • Drag(xStart, yStart, xEnd, yEnd):在屏幕上滑動參數是滑動座標的起始點
  • LongPress(): 長按2s
  • ProfileWait(): 等待5s
  • PressAndHold(x, y, pressDuration) :模擬長按
  • PinchZoom(x1Start, y1Start, x1End, y1End, x2Start, y2Start, x2End, y2End, stepCount): 模擬縮放
  • DispatchString(input): 輸入字符串
  • RunCmd(cmd) :執行shell命令,比如截圖 screencap -p /data/temp/temp.png
  • DispatchFlip(true/false) :打開或者關閉軟鍵盤
  • DeviceWakeUp() :喚醒屏幕

獲取某個界面元素在屏幕上的座標使用sdk中的工具uiautomatorviewer.bat位置在sdk/tools/bin/uiautomatorviewer.bat,雙擊即可運行如下。
在這裏插入圖片描述
開始編寫腳本測試系統計算器 定義一個腳本文件monkey.script

type= raw events
count= 10
speed= 1.0
start data >>

LaunchActivity(com.android.calculator2,com.android.calculator2.Calculator)

#點擊 6  
#使用DispatchPointer(downtime,eventTime,action,x,y,xpressure,size,metastate,xPrecision,yPrecision,device,edgeFlags)來完成
#第三個參數action 0是按下 1是擡起
#使用sdk中的uiautomatorviewer.bat工具來獲取x y的座標  
DispatchPointer(0,0,0,600,1200,0,0,0,0,0,0,0)
DispatchPointer(0,0,1,600,1200,0,0,0,0,0,0,0)

#等待1秒
UserWait(1000)

#點擊 + 號
DispatchPress(KEYCODE_PLUS)
UserWait(1000)

#點擊 9
DispatchPress(KEYCODE_9)
UserWait(1000);

#點擊 = 
Tap(600,1600)
UserWait(1000)

#翻轉屏幕 參數0123分別代表0,90,180,270
#第二個參數 0表示旋轉後恢復,非0則表示固定不變
RotateScreen(2,1)
UserWait(500)

腳本需要運行在手機上,所以先上傳到手機上

adb push monkey.script /sdcard/monkey.script

執行腳本

adb shell monkey -f /sdcard/monkey.script -v -v 1

執行效果如下圖:
在這裏插入圖片描述

Monkey Server

Monkey Server可以讓我們從電腦端直接通過命令操控手機。Monkey Server在官方文檔中沒有介紹,不過源碼中有示例,源碼示例可以在這裏查看README.NETWORK.txt

  • 啓動Monkey Serveradb shell monkey --port 1080 &
  • PC端1080端口數據轉發到客戶端的1080端口 adb forward tcp:1080 tcp:1080
  • 連接Monkey Server並進入控制檯 telnet 127.0.0.1 1080,在這裏面輸入Monkey Server的命令就可以操控手機了。

Monkey Server的常用命令:

  • key [down|up] keycode – 指定Keycode的按鍵事件(分按下、彈起)
  • touch [down|up|move] x y – 指定座標的觸屏操作(分按下、彈起、移動)
  • trackball dx dy – 軌跡球操作
  • tap x y – 指定座標的觸屏操作
  • flip [open|close] – 調用軟鍵盤
  • wake – 喚醒設備
  • press keycode – 指定Keycode的按鍵事件
  • listvar – 列出所有的系統變量
  • getvar varname – 獲取給定系統變量值
  • quit – 退出當前連接,且不接受新的連接
  • done – 退出當前連接,但可以接受新的連接
  • type – 輸入字符

命令執行成功之後會返回OK,注意操作退出telnet前,需要執行done指令,否則再次連接,會報端口已佔用的錯誤。只能重啓設備以釋放端口。

一個一個的輸入命令來控制手機太麻煩,沒人願意使用。Monkey Server也是可以編寫腳本,Linux中可以直接編寫shell腳本即可,Window中可以藉助wscript.shell來完成

定義一個名爲monkey_server_run.vbs的文件來寫腳本

set sh=WScript.CreateObject("WScript.Shell")
WScript.Sleep 2000
sh.SendKeys "open 127.0.0.1 1080 {ENTER}"
WScript.Sleep 2000
sh.SendKeys "press KEYCODE_6 {ENTER}"
WScript.Sleep 2000
sh.SendKeys "press KEYCODE_NUMPAD_ADD {ENTER}"
WScript.Sleep 2000
sh.SendKeys "press KEYCODE_9 {ENTER}"
WScript.Sleep 2000
sh.SendKeys "press KEYCODE_NUMPAD_EQUALS {ENTER}"
WScript.Sleep 2000
sh.SendKeys "done {ENTER}"
WScript.Sleep 1000

注意:這裏有個問題,每次執行sh.SendKeys後面的指令的時候,指令中間的空格都會莫名的消失導致執行失敗,試了一些辦法之後也沒成功,由於Monkey Server的用途也不是很大,前面的Monkey 腳本完全可以完成,後面還有更加強大的MonkeyRunner,遂放棄。

還需要先提前啓動應用,所以使用一個bat批處理來完成下面的一些命令。定義一個文件名爲monkey_server.bat

adb forward tcp:1080 tcp:1080

adb shell am start -n com.android.calculator2/com.android.calculator2.Calculator

start telnet.exe

cscript //nologo .\monkey_server_run.vbs

寫完之後雙擊monkey_server.bat即可運行。

MonkeyRunner

MonkeyRunner也是Android SDK中自帶的一個黑盒測試工具,支持Pyhon和Java,可以實現Monkey無法實現的一些邏輯控制。

先說說這倆後啥區別呢?

  • Monkey是運行在設備上的,可以脫離PC,MonkeyRunner運行在PC上,往手機或模擬器上發送指令來測試。
  • Monkey一般用來做一些隨機性的測試,前面文章也寫了,官方文檔上就寫了隨機測試怎麼用,至於編寫自定義腳本還需要自己看源碼,還是簡單的腳本。MonkeyRunner支持條件判斷,可以寫出更強大的自定義測試腳本。
  • MonkeyRunner可以同時運行多個測試設備,還可以將運行結果截圖並跟已知的一個正確的截圖做比較。

開始

想要運行MonkeyRunner的程序,首先要打開MonkeyRunner的控制界面,無論是官網還是網上的大部分文章說的打開方式都是雙擊打開sdk/tools/monkeyrunner.bat。不過我的sdk中卻沒有,後來在sdk/tools/bin/monkeyrunner.bat找到了它,可惜雙擊沒反應,在cmd窗口中進入到當前文件夾執行monkeyrunner命令報錯

SWT folder '..\framework\x86_64' does not exist.
Please set ANDROID_SWT to point to the folder containing swt.jar for your platform.

我是不是下了個假的sdk?後來通過網上這篇文章解決了大部分問題,因爲用了文章中的方法後還是會報一個錯誤..\framework\adb.exe": CreateProcess error=2, 系統找不到指定的文件搜索了一下adb.exe在\sdk\platform-tools目錄中,拷貝過來之後運行成功。

MonkeyRunner包括三大模塊:

  • MonkeyRunner: 提供了將monkeyrunner程序連接到模擬器或者手機設備的方法。還提供了monkeyrunner程序創建界面和顯示內置幫助的方法
  • MonkeyDevice: 提供了安裝卸載軟件,啓動 Activity以及向設備發送按鍵或者輕觸事件。
  • MonkeyImage:提供了截屏,將位圖轉換爲各種格式,比較兩個MonkeyImage對象和將圖片寫入文件的方法。

這三個模塊都有啥方法可以供我們調用呢,官網有詳細方法列表和解說:MonkeyRunner的MonkeyDevice的MonkeyImage的

使用MonkeyRunner的時候monkeyrunner 工具不會自動導入這些模塊。要導入模塊使用下面的命令

from com.android.monkeyrunner import <module>

其中 是要導入的類名稱。我們可以在同一個 from 語句中導入多個模塊,只需用英文逗號分隔各模塊名稱即可。

簡單小例子:進入monkeyrunner的命令行中輸入下面的指令,可以看到如何操作一臺設備

#導入MonkeyRunner和MonkeyDevice兩個模塊
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
#連接當前設備並返回一個MonkeyDevice對象
device = MonkeyRunner.waitForConnection()
#安裝一個應用,返回值是Boolean類型,可以根據返回值判斷安裝結果
device.installPackage('app-debug.apk')
#定義一個package變量
package="com.chs.androiddailytext"
#定義一個activity變量
activity="com.chs.androiddailytext.MainActivity"
#拼接成要啓動的組件的名稱
runComponent=package + '/' + activity
#啓動組件
device.startActivity(component=runComponent)
#截屏
image=device.takeSnapshot()
#保存截屏的圖片
image.writeToFile('111.png','png')
#按下菜單鍵
device.press('KEYCODE_MENU', MonkeyDevice.DOWN_AND_UP)

MonkeyRunner的錄製回放工具

MonkeyRunner的錄製回放工具用起來很方便,手動操作界面就可以自動生成執行腳本。不過不知道爲啥官網並沒有介紹這倆的用法,需要到源碼中去把腳本拷貝過來自行查看:點擊查源碼,將源碼中的monkey_recorder.py和monkey_playback.py兩個文件拷貝到monkeyrunner.bat的同級目錄下。

  • Monkey_recorder 錄製工具
  • Monkey_playback 回放工具

可以看到這倆文件都是python文件,所以電腦上需要安裝python的環境,具體安裝方法可以去python官網下載安裝

使用Monkey_recorder錄製

雙擊monkey_recorder.py文件就可以啓動錄製工具瞭如下圖
在這裏插入圖片描述
在上圖的手機界面投影中,點擊相應地方,它就會自動生成該位置的點擊事件的腳本,頭部有好幾個菜單,這些菜單也能圖形化的來設置不同的事件

  • Wait : 用來在多個操作之間設置停頓,單位是秒。一般都會設置,因爲自動化執行太快,而且電腦控制手機,之間還會有些延遲,可能PC這邊執行完5個指令了,手機端才執行第二個動作。
  • Press Button:模擬設備上的常用按鍵操作MENU,HOME,SEARCH,BACK
  • TypeSoming:錄入一個字符串,用來模擬輸出
  • Fling:模擬一個滑動操作,可以選擇滑動方向,滑動時長,滑動步數
  • Export Actions:將之前的操作生成的腳本代碼保存到一個文件中,文件後綴名一般爲.mr
  • Refresh Display:刷新界面

下面我們隨便點擊應用中的一些位置,生成的腳本保存如下

TOUCH|{'x':924,'y':1180,'type':'downAndUp',}
WAIT|{'seconds':2.0,}
TOUCH|{'x':465,'y':888,'type':'downAndUp',}
WAIT|{'seconds':2.0,}
TOUCH|{'x':148,'y':752,'type':'downAndUp',}
WAIT|{'seconds':2.0,}
TOUCH|{'x':560,'y':1708,'type':'downAndUp',}
WAIT|{'seconds':2.0,}
TOUCH|{'x':911,'y':1684,'type':'downAndUp',}
WAIT|{'seconds':2.0,}
TOUCH|{'x':182,'y':1704,'type':'downAndUp',}
WAIT|{'seconds':2.0,}
TOUCH|{'x':243,'y':1856,'type':'downAndUp',}
WAIT|{'seconds':2.0,}
TOUCH|{'x':104,'y':528,'type':'downAndUp',}
WAIT|{'seconds':2.0,}
TOUCH|{'x':1366,'y':1848,'type':'downAndUp',}
WAIT|{'seconds':2.0,}

注意:如果我們沒有點擊Wait按鈕添加延時,它是不會自己添加延時的,上面代碼中的延時操作都是自己打開文件添加的,如果不添加延時PC這邊的指令可能嗖的一下就執行完了,而手機那邊可能剛執行了兩個就完了,剩下的執行也接收不到了。

使用monkey_playback.py播放

上面的文件生成了,下面開始播放,到monkeyrunner.bat所在目錄下執行下面命令。如果不想每次都要該文件夾下執行monkeyrunner的命令可以配置一下環境變量。

monkeyrunner %ANDROID_HOME%\tools\bin\monkey_playback.py F:\test\recorder.mr

recorder.mr需要寫絕對路徑,相對路徑運行不成功,另外運行monkey_playback的時候需要把monkey_recorder停掉否則沒效果。我就是一開始沒停掉結果運行回放沒反應,就是不動也沒日誌,找了好久暈。

前面的操作方法基本上都是是基於touch事件的,touch事件是依賴於屏幕的座標值的,而Android手機的碎片化導致有N多種屏幕分辨率的手機。導致從一個手機上生成的腳本在別的手機上運行部正確,無法複用腳本。想要更好的重用的話,可以使用界面上控件的id來做測試。

使用控件的id來做測試,需要用到EasyMonkeyDevice和By這兩個類,這哥倆的用法很網也沒有介紹,只能去源碼中查看點擊查看源碼。不過使用它的話需要測試的手機設備能打開view server。一般情況下只有Android開發版手機 、模擬器、root後的手機才能打開view server。我嘗試了下模擬器沒有成功打開view server就放棄了,畢竟官方也沒推薦使用。後面有更好用的UI Automator、Espresso等工具。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章