這個只是單純的mark一下。還沒有認真去研究。鑑於最近也不會做手機的自動化測試,所以留作以後參考吧。
轉自: http://blog.chengyunfeng.com/?p=504
在Android 4.1釋出的時候包含了一種新的測試工具–uiautomator,uiautomator是用來做UI測試的。也就是普通的手工測試,點選每個控制元件元素 看看輸出的結果是否符合預期。比如 登陸介面 分別輸入正確和錯誤的使用者名稱密碼然後點選登陸按鈕看看是否能否登陸以及是否有錯誤提示等。
功能性或者黑盒UI測試不需要測試人員瞭解程式如何實現的,只需要驗證各種操作的結果是否符合預期即可。這樣的測試可以分離團隊的開發人員和測試人員。大家各幹各的沒有太多的交集。
常用的UI測試方式就是人工驗證啦,就是測試人員拿著各種手機分別安裝要測試的程式然後看看是否能正確完成各種預定的功能。但是這種驗證方式是非常 耗時間的,每次迴歸都要全部驗證一邊,並且還容易出現人為錯誤。比較高效和可靠的UI測試方式就是自動化測試。自動化UI測試建立測試程式碼來執行測試任 務,各種測試任務分別覆蓋不同的使用場景,然後使用測試框架來執行這些測試任務。
uiautomator 就是你的自動化UI測試工具。
概述
Android SDK在4.1中提供瞭如下工具來支援UI自動化測試:
- uiautomatorviewer – 一個圖形介面工具來掃描和分析應用的UI控制元件。
- uiautomator – 一個測試的Java庫,包含了建立UI測試的各種API和執行自動化測試的引擎。
要使用該工具,需要滿足如下條件:
- Android SDK Tools, Revision 21 or higher
- Android SDK Platform, API 16 or higher
下面是uiautomator 工作流程概述:
- 安裝要測試的應用到手機中,分析應用的UI介面元素 並確保被測試應用的各個控制元件可以被測試工具獲取到。
- 建立知道測試案例來模擬應用中的使用者操作步驟。
- 編譯測試案例程式碼為Jar包並複製該Jar包到安裝了待測應用的測試手機中。
- 執行測試並檢視結果
- 修改任何發現的bug,然後修復並重新測試。
分析待測應用的UI元素
在開始編寫測試案例程式碼之前,需要熟悉待測應用的UI元素。可以通過uiautomatorviewer 工具來獲取應用的介面截圖並分析。uiautomatorviewer 工具提供了一個便利的方式來檢視UI佈局結構,並且可以檢視各個控制元件的相關屬性。利用這些資訊可以用來建立UI測試程式碼。
分析待測應用UI介面的步驟如下:
1. 把Android手機連線到電腦上
2. 開啟命令列視窗並導航到目錄 /tools/
執行如下命令:$ uiautomatorviewer
windows下執行 uiautomatorviewer.bat 命令
3. 點選uiautomatorviewer 工具右上角資料夾按鈕旁邊的“Device Screenshot”按鈕來獲取當前 螢幕介面資訊。
注意:如果當前電腦連線了多個裝置,通過設定ANDROID_SERIAL環境變數來指定要分析的裝置。步驟如下:
a.執行如下命令獲取連線到電腦的裝置序列號
$ adb devices
b.設定ANDROID_SERIAL為需要測試的裝置序列號
Windows:set ANDROID_SERIAL=
Unix: export ANDROID_SERIAL=
如果電腦只連線一個裝置則無需設定ANDROID_SERIAL 環境變數。
4. 檢視待測應用的UI介面元素屬性
把滑鼠放到uiautomatorviewer工具左邊的截圖中的控制元件上來檢視該控制元件的屬性。屬性顯示在右側介面下方,上方顯示當前介面的佈局結構。
點選右側上方的黃三角按鈕(Toggle NAF
Nodes)來檢視不能被uiautomator測試工具訪問到的控制元件。這些控制元件只設定了有限的屬性,所以導致uiautomator無法獲取到這些控
件。所以你可能很難測試這些控制元件。這種情況下你可以要求開發者為這些控制元件新增必要的屬性,比如
如果是ImageView或者ImageButton應該新增android:contentDescription屬性。
測試準備工作
在開始使用uiautomator 之前需要完成如下準備工作:
把待測應用安裝到測試手機(裝置)上
當你準備測試的時候,待測的應用可能還沒有釋出到市場上。但是你應該具有該應用的APK安裝檔案,你可以通過ADB工具來安裝待測應用到手機中,或者通過其他工具來安裝Apk。
辨別待測應用UI控制元件
在開始編寫uiautomator測試程式碼之前,需要先辨別待測應用的UI控制元件元素。一般而言,優秀的待測應用的UI元素應該是可見的並且使用者可以操作的。這些UI元素也應該具有可見的文字標籤、android:contentDescription值或者二則兼具。
通過uiautomatorviewer 工具可以檢視應用的可見控制元件。具體使用情況見上面所述。
確保待測應用是可訪問的
由於uiautomator 工具依賴Android裝置的可訪問行來獲取UI控制元件,所以這不是非常重要的。要支援uiautomator 工具需要一下條件:
- 使用android:contentDescription屬性給 ImageButton, ImageView, CheckBox和其他控制元件設定標籤。
- 使用android:hint 屬性來標記EditText 控制元件,而不是使用裡面的文字(文字內容使用者是可以修改的)。
- 對於用來提供操作視覺反饋的UI(文字或者圖示),都新增一個android:hint 屬性來識別。
- 確保所有使用者可操作的介面元素都可以通過方向控制鍵選中(例如軌跡球)。
- 通過uiautomatorviewer 工具來確保所有的UI元素都可以被測試工具訪問到。還可以通過“輔助功能”(在設定介面)中的“TalkBack”等服務來測試UI的可訪問性。
設定開發環境
如果你使用的是Eclipse(Adt),則Android SDK提供了額外的工具來幫助你編寫uiautomator測試程式碼和打包測試專案。在Eclipse中建立uiautomator測試專案的過程如下:
- 建立新的Java專案(注意不是Android專案)。在該專案中來建立測試程式碼。
- 在Project Explorer檢視中,右鍵點選測試專案,選擇“ Properties > Java Build Path”,然後選擇“Libraries” tab介面。在“Libraries”介面選擇“ Add Library > JUnit”來新增JUnit3 庫。然後點選“Add External JARs… ”並導航到Android SDK目錄。選擇platforms目錄下面的 uiautomator.jar 和 android.jar檔案。
- 設定好的build path如下圖:
如果你不使用Eclipse,則需要確保/platforms/目錄中的uiautomator.jar 和 android.jar 位於專案Build path中。
配置好開發環境後就可以開始編寫測試程式碼了。
建立uiautomator 測試案例
uiautomator 測試案例(Test case)需要繼承至UiAutomatorTestCase 類。而UiAutomatorTestCase 類繼承至junit.framework.TestCase類,所以可以用JUnit的Assert類來比較測試結果。
UI測試的首要任務就是訪問測試手機。一般都是從手機的主屏開始測試的。通過uiautomator 提供的API可以從主屏來模擬使用者的操作。下面會介紹具體示例。
uiautomator API
uiautomator API在 uiautomator.jar 檔案中。這些API分別如下:
UiDevice
代表裝置狀態。在測試中,可以通過UiDevice例項來檢測裝置的各種屬性,例如當前的螢幕方向以及螢幕尺寸。同時還可以通過UiDevice例項來執行裝置級別的操作,例如 把裝置設定為橫屏或者豎屏、按下Home按鍵等。
如下是模擬按下Home按鍵的程式碼:
getUiDevice().pressHome();
UiSelector
代表一個搜尋UI控制元件的條件。如果發現多個滿足條件的控制元件則會返回第一個控制元件。返回的結果為UiObject物件。在構造UiSelector的時 候可以組合使用多個屬性來定位具體的控制元件。如果沒有找到控制元件則會丟擲 UiAutomatorObjectNotFoundException 異常。還可以使用childSelector()函式來巢狀UiSelector 物件。例如,下面的程式碼演示瞭如何在當前介面中查詢第一個ListView中的帶有文字屬性為Apps的子控制元件。
UiObject appItem = new UiObject(new UiSelector() .className("android.widget.ListView").instance(1) .childSelector(new UiSelector().text("Apps")));
UiObject
代表一個UI控制元件。通過UiSelector來查詢UiObject。
如下示例程式碼演示瞭如何查詢當前顯示介面中的取消按鈕和確認按鈕:
UiObject cancelButton = new UiObject(new UiSelector().text("Cancel")); UiObject okButton = new UiObject(new UiSelector().text("OK"));
查詢到的UiObject例項可以在其他測試程式碼中重用。需要注意的是:每次使用UiObject做操作的時候uiautomator 都會在當前螢幕重新查詢該控制元件。
如下程式碼uiautomator 工具在當前介面查詢文字內容為“OK”的控制元件。如果存在並且可用則模擬使用者點選該控制元件。
if(okButton.exists() && okButton.isEnabled()) { okButton.click(); }
還可以限制僅僅查詢特定型別的控制元件。例如 如下程式碼只查詢文字為“Cancel”和“OK”的android.widget.Button型別控制元件。
UiObject cancelButton = new UiObject(new UiSelector().text("Cancel") .className("android.widget.Button")); UiObject okButton = new UiObject(new UiSelector().text("OK") .className("android.widget.Button"));
UiCollection
代表控制元件的集合。獲取UiCollection的方式和UiObject一樣,通過 UiSelector查詢。 UiCollection對應Android系統中的ViewGroup以及子控制元件。
如下程式碼演示如何通過UiSelector來獲取包含視訊集合的UiCollection。
UiCollection videos = new UiCollection(new UiSelector() .className("android.widget.FrameLayout"));
如果每個視訊是放到LinearLayout中的,則可以通過如下方式獲取視訊的數目:
int count = videos.getChildCount(new UiSelector() .className("android.widget.LinearLayout"));
如果需要查詢標籤為“Cute Baby Laughing”的視訊,並點選。則可以通過如下方式:
UiObject video = videos.getChildByText(new UiSelector() .className("android.widget.LinearLayout"), "Cute Baby Laughing"); video.click();
同樣還可以模擬其他使用者操作。例如,模擬選擇視訊的操作如下:
UiObject checkBox = video.getChild(new UiSelector() .className("android.widget.Checkbox")); if(!checkBox.isSelected()) checkbox.click();
UiScrollable
代表可滾動的控制元件。可以用UiScrollable來模擬水平或者垂直滾動的UI元素。如果需要操作的元素在螢幕外需要滾動螢幕才能看到的情況下需要使用UiScrollable。
例如,下面的程式碼顯示瞭如何模擬滾動到“Settings ”選單並點選“About tablet”選單的操作。
UiScrollable settingsItem = new UiScrollable(new UiSelector() .className("android.widget.ListView")); UiObject about = settingsItem.getChildByText(new UiSelector() .className("android.widget.LinearLayout"), "About tablet"); about.click()
其他API參考uiautomator api文件。
一個簡單的uiautomator 測試案例
如下是一個簡單的測試案例程式碼,模擬了點選Home鍵回到主屏,然後點選所以應用按鈕開啟所有應用列表,並滾動到時鐘應用。開啟時鐘應用 並選擇鬧鈴介面的第一個鬧鐘設定,修改該設定的開關。然後返回到時鐘介面再進入倒數計時介面。
package com.uia.example.my; import android.widget.ListView; import android.widget.Switch; import com.android.uiautomator.core.UiObject; import com.android.uiautomator.core.UiObjectNotFoundException; import com.android.uiautomator.core.UiScrollable; import com.android.uiautomator.core.UiSelector; import com.android.uiautomator.testrunner.UiAutomatorTestCase; public class LaunchSettings extends UiAutomatorTestCase { // TODO 重要注意: 在執行該測試程式碼的時候 需要先把手機語言環境設定為英文。 public void testDemo() throws UiObjectNotFoundException { // 模擬 HOME 鍵點選事件 getUiDevice().pressHome(); // 現在開啟了主屏應用,模擬點選所有應用按鈕操作來啟動所有應用介面。 // 如果你使用了uiautomatorviewer來檢視主屏,則可以發現“所有應用”按鈕的 // content-description 屬性為“Apps”。可以使用該屬性來找到該按鈕。 UiObject allAppsButton = new UiObject(new UiSelector().description("Apps")); // 模擬點選所有應用按鈕,並等待所有應用介面起來 allAppsButton.clickAndWaitForNewWindow(); // 在所有應用介面,時鐘應用位於Apps tab介面中。下面模擬使用者點選Apps tab操作。 // 找到 Apps tab 按鈕 UiObject appsTab = new UiObject(new UiSelector().text("Apps")); // 模擬點選 Apps tab. appsTab.click(); // 然後在 Apps tab介面,模擬使用者滑動到時鐘應用的操作。 // 由於Apps介面是可以滾動的,所有用 // UiScrollable 物件. UiScrollable appViews = new UiScrollable(new UiSelector().scrollable(true)); // 設定滾動模式為水平滾動(預設為垂直滾動) appViews.setAsHorizontalList(); if (allAppsButton.exists() && allAppsButton.isEnabled()) { // allAppsButton在當前介面已經不可見了 所以這裡不會執行 allAppsButton.click(); } // 查詢時鐘應用並點選 UiObject settingsApp = appViews.getChildByText( new UiSelector().className(android.widget.TextView.class.getName()), "Clock"); settingsApp.clickAndWaitForNewWindow(); // 驗證當前顯示 的應用包名為時鐘 UiObject settingsValidation = new UiObject(new UiSelector().packageName("com.google.android.deskclock")); // 如果不存在則出錯提示 assertTrue("Unable to detect Clock", settingsValidation.exists()); // 模擬點選時間tab UiObject clock = new UiObject(new UiSelector().description("Clock")); clock.clickAndWaitForNewWindow(); // 模擬點選下方的鬧鐘圖示 UiObject alarms = new UiObject(new UiSelector().description("Alarms")); alarms.clickAndWaitForNewWindow(); UiScrollable list = new UiScrollable(new UiSelector().className(ListView.class.getName())); if (list.getChildCount() > 0) { UiObject listIndex0 = list.getChild(new UiSelector().index(0)); UiObject switchBtn = listIndex0.getChild(new UiSelector().className(Switch.class.getName())); boolean isChecked = switchBtn.isChecked(); switchBtn.click(); } // 模擬點選返回鍵 getUiDevice().pressBack(); UiObject timer = new UiObject(new UiSelector().description("Timer")); timer.clickAndWaitForNewWindow(); } }
打包測試程式碼並在測試機上執行
如下步驟打包測試程式碼並在測試機執行的步驟:
1.建立打包測試程式碼的Build指令碼。通過如下命令來生成Build指令碼:
<android-sdk>/tools/android create uitest-project -n <name> -t 1 -p <path>
<name>是包含測試程式碼的專案名稱,<path>是包含測試程式碼的專案檔案路徑。-t後面的1是Android sdk版本id。
注意: 在建立Build指令碼之前,已經建立好了測試專案並編寫好了測試程式碼。只不過該測試專案還沒有包含打包指令碼所以無法打包執行。在建立Build指令碼的時 候,<name>屬性就是測試專案的名稱、<path>就是已經建立的測試專案在電腦中的資料夾路徑。 如果電腦上安裝了多個版本的Android sdk,則需要執行/tools/android list target 來檢視每個SDK的id。選擇4.1以上的id即可。
2. 設定ANDROID_HOME 環境變數。
Windows:set ANDROID_HOME=
Unix:export ANDROID_HOME=
3. 開啟命令列建立,導航到第一步中的目錄中,執行 ant build 來打包。
4. 通過adb push命令把上一步打包出來的jar檔案複製到測試手機中。
adb push <path>/bin/<name>.jar /data/local/tmp/
類似如下程式碼:
adb push ~/dev/workspace/LaunchSettings/bin/LaunchSettings.jar /data/local/tmp/
執行uiautomator 測試
下面是執行 LaunchSettings.jar jar包中測試程式碼的命令。測試程式碼位於com.uia.example.my包中。
adb shell uiautomator runtest LaunchSettings.jar -c com.uia.example.my.LaunchSettings
關於uiautomator 的更多資訊參考這裡:http://developer.android.com/tools/help/uiautomator/index.html
最佳實踐
下面是一些使用uiautomator 做UI測試的最佳實踐
- 在待測應用可能執行的儘可能多的裝置上跑uiautomator 測試。例如 在不同的螢幕密度、不同的螢幕尺寸上執行測試。
- 還應該在一些常規場景下測試UI,例如 電話打入情況、網路連線斷開的情況等。