1、簡述
1.1 總結:
Google官方推薦的UI測試有兩種:單應用界面測試Espresso和多應用界面測試UI Automator (例如與系統(tǒng)應用交互)。兩種都是基于JUnit測試框架實現(xiàn)的,通過Juit框架中的AndroidJUnitRunner運行實現(xiàn),此測試運行程序與 JUnit 3 和 JUnit 4(最高為 JUnit 4.10)測試兼容,都是基于插樁(在實體設備和模擬器上運行)的測試框架??梢曰旌鲜褂茫嗫蓡为毷褂?,但鑒于兩者的差異、APK包容量增加、代碼維護的考量,需根據(jù)需求慎重選擇合適的測試框架方案。
1.2 Espresso 與UI Automator區(qū)別:
涵蓋單個應用的界面測試(Espresso ):這種類型的測試可驗證目標應用在用戶執(zhí)行特定操作或在其 Activity 中輸入特定內容時的行為是否符合預期。它可讓檢查目標應用是否返回正確的界面輸出來響應應用 Activity 中的用戶交互。單應用界面測試框架可讓以編程方式模擬用戶操作,并測試復雜的應用內用戶交互。
涵蓋多個應用的界面測試(UI Automator):這種類型的測試可驗證不同用戶應用之間交互或用戶應用與系統(tǒng)應用之間交互的正確行為。例如,可能想要測試相機應用是否能夠與第三方社交媒體應用或默認的 Android 相冊應用正確分享圖片。支持跨應用交互的界面測試框架可讓針對此類場景創(chuàng)建測試。
2、Espresso 測試框架
2.1簡介
Espresso 測試框架是基于插樁的 API,可與 AndroidJUnitRunner 測試運行程序一起使用。由 AndroidX Test 提供的 Espresso 測試框架提供了一些 API,用于編寫界面測試以模擬單個目標應用內的用戶交互。Espresso 測試可以在搭載 Android 2.3.3(API 級別 10)及更高版本的設備上運行。使用 Espresso 的主要好處在于,它可以自動同步測試操作與正在測試的應用的界面。Espresso 會檢測主線程何時處于空閑狀態(tài),以便可以在適當?shù)臅r間運行測試命令,從而提高測試的可靠性。此外,借助該功能,不必在測試代碼中添加任何計時解決方法,如 Thread.sleep()。
2.2設置 Espresso
在使用 Espresso 構建界面測試之前,請務必設置對 Espresso 庫的依賴項引用:
dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
}
在測試設備上關閉動畫 - 如果讓系統(tǒng)動畫在測試設備上保持開啟狀態(tài),可能會導致意外結果或導致測試失敗。通過以下方式關閉動畫:在“設置”中打開“開發(fā)者選項”,然后關閉以下所有選項:窗口動畫縮放、過渡動畫縮放、Animator 時長縮放
2.3創(chuàng)建 Espresso 測試類
如需創(chuàng)建 Espresso 測試,請遵循以下編程模型:
通過調用 onView() 方法或 AdapterView 控件的 onData() 方法,在 Activity 中找到要測試的界面組件(例如,應用中的登錄按鈕)。
通過調用 ViewInteraction.perform() 或 DataInteraction.perform()方法并傳入用戶操作(例如,點擊登錄按鈕),模擬要在該界面組件上執(zhí)行的特定用戶交互。如需對同一界面組件上的多項操作進行排序,請在方法參數(shù)中使用逗號分隔列表將它們鏈接起來。
根據(jù)需要重復上述步驟,以模擬目標應用中跨多個 Activity 的用戶流。
執(zhí)行這些用戶交互后,使用 ViewAssertions 方法檢查界面是否反映了預期的狀態(tài)或行為。
2.4 Espresso 與 ActivityTestRule 一起使用
下文介紹如何創(chuàng)建新的 JUnit 4 型 Espresso 測試,并使用 ActivityTestRule 減少需要編寫的樣板代碼量。通過使用 ActivityTestRule,測試框架會在帶有 @Test 注釋的每個測試方法運行之前以及帶有 @Before 注釋的所有方法運行之前啟動被測 Activity。該框架將在測試完成并且?guī)в?@After 注釋的所有方法都運行后關閉該 Activity。
2.5訪問界面組件
必須先指定界面組件或視圖,然后 Espresso 才能與被測應用進行交互。Espresso 支持使用 Hamcrest 匹配器指定應用中的視圖和適配器。
如需查看視圖,請調用 onView() 方法并傳入用于指定目標視圖的視圖匹配器。指定視圖匹配器部分對此進行了更詳細的說明。onView() 方法將返回一個 ViewInteraction 對象,該對象允許測試與視圖進行交互。但是,如果希望在 RecyclerView 布局中查找視圖,調用 onView() 方法可能不起作用。在這種情況下,請按照在 AdapterView 中查找視圖中的說明進行操作。
注意:onView() 方法不檢查指定的視圖是否有效。相反,Espresso 根據(jù)提供的匹配器僅搜索當前視圖層次結構。如果未找到匹配項,該方法會拋出 NoMatchingViewException。
2.6指定視圖匹配器
可以使用以下方法指定視圖匹配器:
調用 ViewMatchers 類中的方法。不能保證 Android 資源 ID 是唯一的。如果測試嘗試匹配由多個視圖使用的某個資源 ID,Espresso 會拋出 AmbiguousViewMatcherException。
使用 Matchers 類??梢允褂?allOf() 方法組合多個匹配器,例如 containsString() 和 instanceOf()。此方法可讓更精細地過濾匹配結果。可以使用 not 關鍵字過濾與匹配器不對應的視圖,如需在測試中使用這些方法,請導入 org.hamcrest.Matchers 軟件包。如需詳細了解 Hamcrest 匹配,請訪問 Hamcrest 網(wǎng)站。
如需提高 Espresso 測試的性能,請指定查找目標視圖所需的最少匹配信息。例如,如果某個視圖可通過其描述性文本進行唯一標識,無需指定該視圖也可從 TextView 實例分配。
2.7在 AdapterView 中查找視圖
在 AdapterView 微件中,視圖會在運行時由子視圖動態(tài)填充。如果要測試的目標視圖位于 AdapterView(例如 ListView、GridView 或 Spinner)內,則 onView() 方法可能不起作用,因為只能將一部分視圖加載到當前視圖層次結構中。
應改為調用 onData()方法獲取 DataInteraction 對象,以訪問目標視圖元素。Espresso 負責將目標視圖元素加載到當前視圖層次結構中。Espresso 還負責滾動到目標元素,并將該元素置于焦點上。
注意:onData() 方法不檢查指定的項是否與視圖對應。Espresso 僅搜索當前視圖層次結構。如果未找到匹配項,該方法會拋出 NoMatchingViewException。
2.8執(zhí)行操作
調用 ViewInteraction.perform() 或 DataInteraction.perform() 方法,以模擬界面組件上的用戶交互。必須將一個或多個 ViewAction 對象作為參數(shù)傳入。Espresso 將按照給定的順序依次觸發(fā)每項操作,并在主線程中執(zhí)行這些操作。
ViewActions 類提供了用于指定常見操作的輔助程序方法的列表??梢詫⑦@些方法用作方便的快捷方式,而不是創(chuàng)建和配置單個 ViewAction 對象。可以指定以下操作:
ViewActions.click():點擊視圖。
ViewActions.typeText():點擊視圖并輸入指定的字符串。
ViewActions.scrollTo():滾動到視圖。目標視圖必須是由 ScrollView 派生的子類,并且其 android:visibility 屬性的值必須為 VISIBLE。對于擴展 AdapterView 的視圖(例如 ListView),onData() 方法將負責為滾動。
ViewActions.pressKey():使用指定的鍵碼執(zhí)行按鍵操作。
ViewActions.clearText():清除目標視圖中的文本。
如果目標視圖位于 ScrollView 內,請先執(zhí)行 ViewActions.scrollTo() 操作以在屏幕中顯示該視圖,然后再繼續(xù)執(zhí)行其他操作。如果已顯示該視圖,則 ViewActions.scrollTo() 操作將不起作用。
2.9使用 Espresso Intent 單獨測試 Activity
Espresso Intent 支持對應用發(fā)出的 intent 進行驗證和打樁。使用 Espresso Intent,可以通過以下方式單獨測試應用、Activity 或服務:攔截傳出 intent,對結果進行打樁,然后將其發(fā)送回被測組件。
如需開始使用 Espresso Intent 進行測試,需要將以下代碼行添加到應用的 build.gradle 文件中:
dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0'
}
如需測試 intent,需要創(chuàng)建 IntentsTestRule 類(與 ActivityTestRule 類非常相似)的實例。IntentsTestRule 類會在每次測試前初始化 Espresso Intent,終止托管 Activity,并在每次測試后釋放 Espresso Intent。
2.10使用 Espresso Web 測試 WebView
使用 Espresso Web,可以測試包含在 Activity 中的 WebView 組件。它使用 WebDriver API 檢查和控制 WebView 的行為。
如需開始使用 Espresso Web 進行測試,需要將以下代碼行添加到應用的 build.gradle 文件中:
dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-web:3.1.0'
}
在使用 Espresso Web 創(chuàng)建測試的過程中,當實例化 ActivityTestRule 對象以測試 Activity 時,需要在 WebView 上啟用 JavaScript。在測試中,可以選擇 WebView 中顯示的 HTML 元素并模擬用戶交互,例如在文本框中輸入文本,然后點擊某個按鈕。完成這些操作后,可以驗證網(wǎng)頁上的結果是否與預期結果一致。
2.11驗證結果
調用 ViewInteraction.check() 或 DataInteraction.check() 方法以斷言界面中的視圖與某種預期狀態(tài)匹配。必須將 ViewAssertion 對象作為參數(shù)傳入。如果斷言失敗,Espresso 會拋出 AssertionFailedError。
ViewAssertions 類提供了用于指定常見斷言的輔助程序方法的列表。
可以使用的斷言包括:
doesNotExist:斷言當前視圖層次結構中沒有符合指定條件的視圖。
matches:斷言當前視圖層次結構中存在指定的視圖,并且其狀態(tài)與某個給定的 Hamcrst 匹配器匹配。
selectedDescendentsMatch:斷言存在父視圖的指定子視圖,并且其狀態(tài)與某個給定的 Hamcrst 匹配器匹配。
2.12在設備或模擬器上運行 Espresso 測試
可以通過 Android Studio 或命令行運行 Espresso 測試。請務必在項目中將 AndroidJUnitRunner 指定為默認插樁測試運行程序。
如需運行 Espresso 測試,請按照測試入門中所述的插樁測試運行步驟進行操作。
3、UI Automator 測試框架
3.1簡介
UI Automator 測試框架是基于插樁的 API,可與 AndroidJUnitRunner 測試運行程序一起使用。通過涉及多個應用中的用戶交互的界面測試,可以驗證當用戶流跨入其他應用或系統(tǒng)界面時,的應用是否能夠正常運行。短信應用就是此類用戶流的一個例子,該應用先讓用戶輸入短信,再啟動 Android 聯(lián)系人選擇器,以便用戶可以選擇短信的收件人,然后將控制權返還給原來的應用,以便用戶提交短信。
使用 AndroidX Test 提供的 UI Automator 測試框架來編寫此類界面測試。通過 UI Automator API,可以與設備上的可見元素進行交互,而不管焦點在哪個 Activity 上。的測試可以使用方便的描述符(如顯示在相應組件中的文本或其內容描述)來查找界面組件。UI Automator 測試可以在搭載 Android 4.3(API 級別 18)或更高版本的設備上運行。
3.2設置 UI Automator
在使用 UI Automator 構建界面測試之前,請務必配置測試源代碼位置和項目依賴項,如針對 AndroidX Test 設置項目中所述。
在 Android 應用模塊的 build.gradle 文件中,必須設置對 UI Automator 庫的依賴項引用:
dependencies {
...
androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'
}
要優(yōu)化 UI Automator 測試,應先檢查目標應用的界面組件并確保它們可訪問。這些優(yōu)化提示將在接下來的兩部分中進行介紹。
3.3檢查設備上的界面
在設計測試之前,請先檢查設備上可見的界面組件。要確保 UI Automator 測試可以訪問這些組件,請檢查這些組件是否具有可見文本標簽和/或 android:contentDescription 值。
uiautomatorviewer 工具提供了一個方便的可視界面,用于檢查布局層次結構以及查看在設備前臺顯示的界面組件的屬性。利用此信息,可以使用 UI Automator 創(chuàng)建更精細的測試。例如,可以創(chuàng)建與特定可見屬性匹配的界面選擇器。
要啟動 uiautomatorviewer 工具,請執(zhí)行以下操作:
在實體設備上啟動目標應用。
將設備連接到開發(fā)機器。
打開終端窗口并導航至 <android-sdk>/tools/ 目錄。
使用以下命令運行該工具:
$ uiautomatorviewer
如需查看應用的界面屬性,請執(zhí)行以下操作:
在 uiautomatorviewer 界面中,點擊 Device Screenshot 按鈕。
將鼠標懸停在左側面板中的快照上,以查看 uiautomatorviewer 工具識別的界面組件。右下方的面板中列出了屬性,右上方的面板中列出了布局層次結構。
(可選)點擊 Toggle NAF Nodes 按鈕,以查看 UI Automator 無法訪問的界面組件。對于這些組件,系統(tǒng)顯示的相關信息可能很有限。
3.4確保 Activity 可訪問
UI Automator 測試框架在已實現(xiàn) Android 無障礙功能的應用上效果更好。當使用類型為 View 或 SDK 中的 View 的子類的界面元素時,無需實現(xiàn)無障礙功能支持,因為這些類已經(jīng)為實現(xiàn)了這項支持。
不過,某些應用會使用自定義界面元素來提供更豐富的用戶體驗。此類元素不會提供自動無障礙功能支持。如果的應用包含不是 SDK 中的 View 的子類的實例,請務必向這些元素添加無障礙功能,具體操作步驟如下:
創(chuàng)建一個擴展 ExploreByTouchHelper 的具體類。
通過調用 setAccessibilityDelegate(),將新類的實例與特定自定義界面元素相關聯(lián)。
如需獲得有關向自定義視圖元素添加無障礙功能的其他指導,請參閱構建無障礙自定義視圖。如需詳細了解 Android 平臺上無障礙功能的常規(guī)最佳做法,請參閱改進應用的無障礙功能。
3.5創(chuàng)建 UI Automator 測試類
UI Automator 測試類的編寫方式應與 JUnit 4 測試類相同。如需詳細了解如何創(chuàng)建 JUnit 4 測試類以及如何使用 JUnit 4 斷言和注釋,請參閱創(chuàng)建插樁單元測試類。
在測試類定義的開頭添加 @RunWith(AndroidJUnit4.class) 注釋。還需要將 AndroidX Test 中提供的 AndroidJUnitRunner 類指定為默認測試運行程序。在設備或模擬器上運行 UI Automator 測試部分對此步驟進行了更詳細的說明。
在 UI Automator 測試類中實現(xiàn)以下編程模型:
通過調用 getInstance() 方法并將 Instrumentation 對象作為參數(shù)傳遞給該方法,獲取 UiDevice 對象以訪問要測試的設備。
通過調用 findObject() 方法,獲取 UiObject 對象以訪問設備上顯示的界面組件(例如,前臺的當前視圖)。
通過調用 UiObject 方法,模擬需要在該界面組件上執(zhí)行的特定用戶交互;例如,調用 performMultiPointerGesture() 以模擬多點觸控手勢,以及調用 setText() 以修改文本字段??梢愿鶕?jù)需要反復調用第 2 步和第 3 步中的 API,以測試涉及多個界面組件或用戶操作序列的更復雜的用戶交互。
執(zhí)行這些用戶交互后,檢查界面是否反映了預期的狀態(tài)或行為。
下面幾部分更詳細地介紹了這些步驟。
3.6訪問界面組件
UiDevice 對象是訪問和操縱設備狀態(tài)的主要方式。在測試中,可以調用 UiDevice 方法檢查各種屬性的狀態(tài),如當前屏幕方向或顯示屏尺寸。的測試可以使用 UiDevice 對象執(zhí)行設備級操作,如強制設備進行特定旋轉、按方向鍵硬件按鈕,以及按主屏幕和菜單按鈕。
最好從設備的主屏幕開始測試。在主屏幕(或在設備中選擇的其他某個起始位置)上,可以調用 UI Automator API 提供的方法,以選擇特定的界面元素并與之交互。
在某些情況測試中,例如@SdkSuppress(minSdkVersion = 18) 語句有助于確保測試只能在搭載 Android 4.3(API 級別 18)或更高版本的設備上運行(根據(jù) Android Automator 框架的要求)。
使用 findObject() 方法檢索 UiObject,它表示符合給定選擇器條件的視圖??梢愿鶕?jù)需要重復使用已在應用測試的其他部分中創(chuàng)建的 UiObject 實例。請注意,每當?shù)臏y試使用 UiObject 實例以點擊界面元素或查詢屬性時,UI Automator 測試框架都會在當前顯示內容中搜索匹配項。
3.7指定選擇器
如果需要訪問應用中的特定界面組件,請使用 UiSelector 類。此類表示對當前顯示的界面中特定元素的查詢。
如果找到了多個匹配元素,系統(tǒng)會將布局層次結構中的第一個匹配元素作為目標 UiObject 返回。構建 UiSelector 時,可以將多個屬性鏈接在一起以優(yōu)化搜索。如果未找到匹配的界面元素,系統(tǒng)會拋出 UiAutomatorObjectNotFoundException。
可以使用 childSelector() 方法來嵌套多個 UiSelector 個實例。
最佳做法是,在指定選擇器時,應使用資源 ID(如果已將其分配給界面元素),而不是文本元素或內容描述符。并非所有元素都有文本元素(例如,工具欄中的圖標)。文本選擇器很脆弱,如果界面發(fā)生細微更改,可能會導致測試失敗。此外,文本選擇器也可能無法在不同語言之間擴展,它們可能與翻譯的字符串不匹配。
在選擇器條件中指定對象狀態(tài)可能很有用。例如,如果要選擇所有已選中元素的列表以便取消選中這些元素,請調用 checked() 方法并將參數(shù)設置為 true。
3.8執(zhí)行操作
的測試獲取 UiObject 對象后,可以調用 UiObject 類中的方法,在由該對象表示的界面組件上執(zhí)行用戶交互??梢灾付ㄈ缦虏僮鳎?/p>
click():點擊界面元素的可見邊界的中心。
dragTo():將此對象拖動到任意坐標。
setText():清除可修改字段的內容后,設置該字段中的文本。相反,clearTextField() 方法用于清除可修改字段中的現(xiàn)有文本。
swipeUp():對 UiObject 執(zhí)行向上滑動操作。同樣,swipeDown()、swipeLeft() 和 swipeRight() 方法用于執(zhí)行相應的操作。
通過 UI Automator 測試框架,可以發(fā)送 Intent 或啟動 Activity,無需使用 shell 命令,只需通過 getContext() 獲取 Context 對象即可。
3.8.1對集合執(zhí)行操作
如果需要模擬內容集合(例如,音樂專輯中的歌曲或收件箱中的電子郵件列表)上的用戶交互,請使用 UiCollection 類。要創(chuàng)建 UiCollection 對象,請指定 UiSelector,用于搜索其他子界面元素的界面容器或封裝容器,如包含子界面元素的布局視圖。
3.8.2對可滾動視圖執(zhí)行操作
使用 UiScrollable 類模擬顯示屏上的垂直或水平滾動。當界面元素位于屏幕外而需要滾動屏幕以使其進入視野時,此方法很有用。
3.9驗證結果
InstrumentationTestCase 擴展了 TestCase,因此可以使用標準的 JUnit Assert 方法測試應用中的界面組件是否會返回預期結果。
3.10在設備或模擬器上運行 UI Automator 測試
可以通過 Android Studio 或命令行運行 UI Automator 測試。請務必在項目中將 AndroidJUnitRunner 指定為默認插樁測試運行程序。