測試是應用開發流程中的重要環節。 對於 Android,這尤爲重要,因爲 Android 設備彼此之間差異很大,主要體現在以下幾個方面:
- 屏幕尺寸和分辨率
- Android 版本
- 外形
- 處理器的指令集
- 是否有前置攝像頭、NFC、外置鍵盤等。
您應在多臺設備上對 Android 應用進行測試。
應用測試流程包括多種測試。 讓我們來了解一下手動功能測試。 測試者需要認真檢查所有功能並將設備重置爲初始狀態。 測試者在每個應用和每部設備上重複上述操作。 該流程是手動完成的,因此非常耗時。
自動功能測試可按計劃執行而無需額外成本。 例如,測試一個 build,每天晚上在所有設備上進行測試,早上分析結果並修復漏洞。
在本文中,我們將回顧幾種適用於自動功能測試的工具。 我僅對 Android SDK 中包括的或在開源許可協議下發布的工具進行介紹。
自動測試的概念
我們的目標是將手動執行的操作自動化,以實現最大精度。 讓我們瞭解一下這些操作。 我們將使用多個應用和多部 Android 設備。
對於每個應用和每部設備,我們應按照下列步驟來操作:
- 在設備上安裝應用
- 啓動應用
- 使用指定方法測試應用
- 卸載應用
- 將設備重置爲初始階段
在每個步驟中,您需要收集和分析數據,如日誌和截屏。 在下文中,我們將討論將這些步驟自動化的工具。
控制 Android 設備
首先,您需要選擇用於運行自動化測試的電腦,並在該電腦上安裝 Android SDK。 我將以運行 Linux* 系統的臺式電腦爲例。 您需要在每臺設備上禁用鎖屏並將“進入睡眠模式的時間”調整到最大值。對於一些方法 您需要禁用屏幕方向調整。
Android SDK 中有兩種實用程序可以控制 Android 設備: ADB 和 monkeyrunner*。 下面,我將具體介紹如何將手動測試中的操作自動化。
使用 ADB 控制 Android 設備
ADB (Android Debug Bridge)是控制 Android 設備的命令行工具。 ADB 主頁是: http://developer.android.com/tools/help/adb.html
ADB 工具位於 <android_sdk>/platform-tools/
目錄下。您需要將該目錄存放到 PATH
環境變量下。
檢查 ADB 安裝
安裝並設置 Android SDK,然後將 Android 設備連接至您的電腦並運行下列命令:
adb devices
該命令將出現在所有插入的 Android 設備上。 如果設備列表不是空白,那麼 ADB 便可正常運行。
在多臺設備上運行
您需要使用“-s”參數指定 ADB 應使用哪臺設備。
adb -s [serial_number] [command]
例如:
adb -s [serial_number] logcat
設備的序列號可通過輸入 «adb devices» 命令後生成的輸出中獲得。 參數 -s
支持您同時使用多臺互聯設備。
基本的 ADB 命令
在設備上打開控制檯:
adb shell
在設備上運行命令:
adb shell [command]
Android 中包含許多標準的 Linux 實用程序: ls、cat、dmesg ...
從 apk 文件安裝應用:
adb install example.apk
卸載應用:
adb uninstall [package]
從 apk 文件獲取程序包名稱:
aapt dump badging example.apk | grep "Package"
從設備將文件下載至電腦:
adb pull [path-on-device] [file]
從設備將文件上傳至電腦:
adb push [file] [path-on-device]
注:
Android 設備上的大多數目錄僅支持讀取訪問。 /sdcard
(但是您無法從該目錄下運行程序)和 /data/local/tmp
支持寫入訪問。
啓動應用:
adb shell am start -n [package]/[activity]
運行指定活動。
您可以從 apk 文件抽取活動名稱:
aapt dump badging example.apk | grep "launchable-activity"
讀取日誌
Logcat 是從 Android 設備讀取日誌的命令。
Logcat 主頁:http://developer.android.com/tools/help/logcat.html
從設備讀取日誌(按下 Ctrl-C 解除阻止):
adb logcat
清除設備上的日誌緩存:
adb logcat -c
將日誌緩存轉儲到設備上(顯示當前的緩存內容,未阻止):
adb logcat -d
示例:
1
adb logcat -c
# clear the buffer log
2
# Action
3
adb logcat -d >
file
.log
# save the current contents of the log buffer to file.log
使用 screencap 截取屏幕
screencap
實用程序將當前的屏幕內容保存爲圖形文件:
1
adb shell screencap /sdcard/
screen
.png
2
adb pull /sdcard/
screen
.png
screen
.png
3
adb shell
rm
/sdcard /
screen
.png
screencap
實用程序可在安裝了 Android 4.x 和更高版本的手機上使用。 在低於 Android 4.x 的版本上,您可以使用 monkeyrunner 來截取屏幕。
使用 ADB 運行 BASH 腳本來測試應用
腳本: app_test.sh
使用 MonkeyRunner 控制 Android 設備
monkeyrunner 工具可爲腳本提供控制 Android 設備的 API。 您可以使用 monkeyrunner 編寫 Python* 腳本來安裝、啓動 Android 應用,模擬用戶操作,獲取截圖並將其保存至電腦。 Monkeyrunner 使用 Jython* 運行腳本。
monkeyrunner 主頁和 API 參考: http://developer.android.com/tools/help/monkeyrunner_concepts.html
使用 monkeyrunner 讀取日誌
File log.py:
01
# coding: utf-8
02
from
com.android.monkeyrunner
import
MonkeyRunner, MonkeyDevice
03
04
def
log(fn, device):
05
msg
=
device.shell(
'logcat -d'
)
06
f_log
=
open
(fn,
'at'
)
07
if
msg
is
None
:
08
msg
=
'None'
09
f_log.write(msg.encode(
'utf-8'
))
10
f_log.close()
11
device.shell(
'logcat -c'
)
12
13
if
__name__
=
=
'__main__'
:
14
device
=
MonkeyRunner.waitForConnection()
15
device.shell(
'logcat -c'
)
# Clear logs buffer
16
# ...
17
log(
'example.log'
, device)
# Write logs
開始:
monkeyrunner log.py
腳本將會把日誌寫入當前目錄下名爲“文件示例.log”的文件。
使用 MonkeyRunner 捕捉截圖
File screen.py:
1
# coding: utf-8
2
from
com.android.monkeyrunner
import
MonkeyRunner, MonkeyDevice
3
4
if
__name__
=
=
'__main__'
:
5
device
=
MonkeyRunner.waitForConnection()
6
image
=
device.takeSnapshot()
7
image.writeToFile(
'screenshot.png'
,
'png'
)
開始:
monkeyrunner screen.py
腳本捕捉截圖並在當前目錄下將其保存爲名爲 filescreenshot.png 文件。
示例:使用 monkeyrunner 控制設備
開始:
monkeyrunner monkeyrunner_test.py
自動測試方法
使用 Monkey* 進行測試
試想將正在測試的設備交給一隻非常敏捷且極富創造力的猴子 — Monkey(猴子)工具的設計便是模擬這種情形。Monkey 工具是 Android SDK 的組成部分,可發送一連串的隨機用戶事件。命令行參數可指定用戶操作次數、每類事件的比率和程序包的名稱(因此,Monkey 的操作不會超出所測試應用的限度,且不會向地址簿中的任何聯繫人發送 SMS)。
Monkey 主頁上提供了諸多示例和參數列表: http://developer.android.com/tools/help/monkey.html
Monkey 工具的主要優點是零維護成本。 而且,壓力測試還可檢測出 non-trivial 漏洞。
使用 Monkey 工具進行測試的缺點:
- Monkey 無法模擬複雜的工作負載,如身份驗證。 因此,應用的功能性無法進行測試。
- 需要複雜控制(快速反應和複雜手勢)的遊戲應在開始時完成,或不要執行該類應用的測試。
- Monkey 發現的錯誤很難再現。
- Monkey 無法在測試過程中檢查應用狀態。
對於任何應用而言,開始都可以先使用 Monkey 進行自動測試。 這種方法可爲具體應用提供充足的結果。如果測試質量較低,您需要使用其他測試方法。
使用 MonkeyRunner 進行測試
使用 MonkeyRunner,您不僅可以開發 Android 設備控制腳本,還可以編寫腳本在特定設備上測試應用。
優點:
- 靈活。
缺點:
- 編寫腳本較複雜 — 即使是在簡單的情況下。
開發 MonkeyRunner 需要花費很長的時間,因此通常這種方法不太理想。但是在某些情況下可以使用這種方法。
使用 getevent 和 sendevent 進行測試
Getevent 和 sendevent 實用程序支持用戶記錄事件序列並將其再現。運行這些工具不需要根許可。
優點:
- 在手動測試下,無需花費額外成本便可記錄事件序列(如果執行)。
- 記錄事件序列不需要編程技能。
缺點:
- 需單獨爲每個應用和每部設備記錄序列。如果您更改了一個應用界面,需要重新記錄所有已記錄的操作。
- 這種方法無法在測試過程中檢查應用狀態。 如果應用響應延遲(如網頁加載),測試結果將出現錯誤。
- 演示快速、複雜的序列所需的時間比記錄的時間長。 因此,有時候這種方法不適合測試響應時間較爲關鍵的動態遊戲(dynamic game)。
記錄事件序列:
01
# Record event sequence
02
# Do actions on the device, press Ctrl-C to finish
03
adb shell getevent -t > events.txt
04
# Convert event sequence to script
05
./decode_events.py events.txt > events.sh
06
# Load the script to the device
07
adb push events.sh /data/
local
/tmp/
08
# Set the permissions
09
adb shell
chmod
755 /data/
local
/tmp/events.sh
10
# Run script
11
adb shell sh /data/
local
/tmp/events.sh
腳本: decode_events.py
在設備上再現記錄的事件序列。
使用 Robotium* 進行測試
Robotium 未包含在 Android SDK 中,但是它是在開源協議下發布的產品。 Robotium 主頁是: http://code.google.com/p/robotium/。
Robotium 腳本可在應用 UI 層面而非輸入設備層面定義操作。
例如,腳本需要點擊 «OK» 按鈕。 monkeyrunner 腳本將按照“點擊屏幕點(x0, y0)”執行。 Robotium 腳本將按照“按下帶有文本“OK”的按鈕”執行。
當在界面層面描述操作時,測試腳本將不受界面佈局、界面分辨率和方向的影響。
此外,Robotium 還支持您檢查應用對操作的響應。例如,點擊 «OK» 按鈕後,將會出現帶有“Item 1”的列表項目。您還可以使用 Robotium 查看列表元素的名稱。 如果您可以在每一步之後檢查應用狀態,便很容易找到錯誤出現在哪一步。
缺點:
- 您需要在 Java* 中爲每個應用開發一個測試腳本。 這需要編程技巧,也較爲費時。
- 應用界面更改後,必須重新安排事件序列。
- 相比使用 getevent / sendevent 而言,編寫 Robotium 校本更爲困難。
一般而言,Robotium 支持您以適度的成本開發最高質量的測試案例。
測試方法比較
測試方法 | 優點 | 缺點 |
---|---|---|
Monkey — 一連串隨機用戶操作 |
無維護成本。 |
測試質量在不同的應用上會有所差異。 Monkey 無法在測試過程中檢查應用狀態。 |
monkeyrunner — 設備控制腳本 |
靈活性 |
編寫腳本較複雜 — 即使針對簡單的應用。 |
getevent/sendevent — 記錄/再現用戶操作 |
記錄事件序列不需要編程技能。 |
記錄的操作序列僅可在一臺設備上以固定的界面方向執行。 應用界面更改後,必須重新安排事件序列。 這種方法無法在測試過程中檢查應用的狀態。 |
Robotium — 測試腳本 API 以驗證狀態 |
操作在應用 UI 層面描述。 腳本可能不會受到界面分辨率和界面方向的影響。 腳本可在一個操作後檢查應用狀態。 |
在 Java 編寫腳本較複雜。 如果您更改了應用界面,將需要修改腳本。 |
結果分析
現在,我們需要分析在自動錯誤測試流程過程中收集的日誌和截屏。
日誌分析
您可以搜索一下以下的字符串:
- I/DEBUG
- FATAL EXCEPTION
- WIN DEATH
您可以在該列表中添加在手動測試中發現的錯誤消息。
截屏分析
您可以準備一系列測試關鍵時刻的截屏,並在自動測試時將其與屏幕內容進行對比。 這可以確定自動測試流程是否正常運行。
將最初的截屏與應用啓動後的截屏進行對比非常有用。 它可以在應用出現靜默故障時檢查事件。
Monkeyrunner 支持您按照指定的容錯性(百分比)對比兩個截屏:
1
image1
=
device.takeSnapshot()
2
# ...
3
image2
=
device.takeSnapshot()
4
if
image2.sameAs(image1,
0.1
):
5
'image1 and image2 are the same (10%)'
很遺憾,沒有 MonkeyImage API 可用於加載文件中的圖片。 您可以使用,如 Python* Imaging Library 編寫一個自定義功能來對比圖片。
將設備重置爲初始狀態
您應在測試後將設備重置會初始狀態。這可以通過下列幾種方法來實現:
- 多次按下 «Back» 按鈕。
- 重啓設備。
- 重啓 zygote 流程。
通常情況下,第一個選項最合適。
多次按下 Back 按鈕
使用 monkeyrunner 按 “Back” 按鈕:
1
for
i
in
xrange
(
0
,
10
):
2
device.press(
'KEYCODE_BACK'
, MonkeyDevice.DOWN_AND_UP)
3
time.sleep(
0.5
)
在實際情況下這是較好的選擇,因爲它不需要用戶實際操作。
結論
在本文中,我們介紹了幾種針對 Android 應用的自動測試方法。 我們回顧了自動測試方法的優點和缺點。
此外,我們還討論了 Android SDK 中的 Monkey 和 monkeyrunner 工具以及 Robotium 工具。
自動測試不能取代其他類型的測試。正確的有組織的測試流程(結合包括自動測試在內的不同測試方法)是高質量應用開發流程的必要部分。