Espresso-Web 是用來處理 Android WebView UI 元件的進入點。 Espresso-Web 會重複使用熱門 WebDriver API 中的 Atom,檢查及控管 WebView 的行為。
Espresso-Web 的適用時機
使用 Espresso-Web 測試混合型應用程式,尤其是應用程式原生 UI 元件與 WebView
UI 元件的整合。您可以搭配使用 Espresso-Web API 與其他 Espresso API,與 WebView
物件內的網頁元素充分互動。
如果您只需要測試 WebView
本身,而非應用程式中 WebView
與原生元件之間的互動,請考慮使用 WebDriver 等架構編寫一般網頁測試。如果您使用網路測試架構,就不需要使用 Android 裝置或 Java 虛擬機器,因此測試執行速度更快,也更可靠。不過,Espresso-Web 可讓您重複使用自訂 WebDriver 原子,因此具有高度彈性,特別是在編寫要針對獨立網頁應用程式和包含 Android UI 的應用程式執行的測試時。
運作方式
與 Espresso 的 onData()
方法類似,WebView
互動包含多個 Atom。WebView
互動會結合 Java 程式設計語言和 JavaScript 橋接器來執行工作。由於從 JavaScript 環境公開資料不會造成競爭條件,因此完全支援從 Web.WebInteraction
物件傳回資料,讓您驗證從要求傳回的所有資料。這是因為 Espresso 在 Java 端看到的所有內容都是獨立副本。
什麼是 WebDriver Atom?
WebDriver 架構會使用 Atom,以程式輔助方式尋找及操控網頁元素。WebDriver 會使用 Atom 來操控瀏覽器。從概念上來說,Atom 與 ViewAction
類似,都是獨立單元,可在 UI 中執行動作。您可以使用定義的方法清單 (例如 findElement()
和 getElement()
) 公開 Atom,從使用者的角度驅動瀏覽器。不過,如果您直接使用 WebDriver 架構,就必須妥善安排 Atoms,這需要相當冗長的邏輯。
在 Espresso 中,Web
和 Web.WebInteraction
類別會包裝這個樣板,並提供與 WebView 物件互動的 Espresso 類似體驗。因此在 WebView
的環境中,Atoms 可用來取代傳統的 Espresso ViewMatchers
和 ViewActions
。
這個 API 隨後會變得相當簡單:
Kotlin
onWebView() .withElement(Atom) .perform(Atom) .check(WebAssertion)
Java
onWebView() .withElement(Atom) .perform(Atom) .check(WebAssertion);
詳情請參閱 Selenium 的 Atoms 說明文件。
實作 WebView
請按照下列各節的操作說明,在應用程式測試中使用 WebView
。
套件
如要在專案中加入 Espresso-Web,請完成下列步驟:
- 開啟應用程式的
build.gradle
檔案。這通常不是頂層build.gradle
檔案,而是app/build.gradle
。 在依附元件中新增下列程式碼:
Groovy
androidTestImplementation 'androidx.test.espresso:espresso-web:3.6.1'
Kotlin
androidTestImplementation('androidx.test.espresso:espresso-web:3.6.1')
Espresso-Web 僅與 Espresso 2.2 以上版本和測試程式庫 0.3 以上版本相容,因此請務必一併更新這些程式碼行:
Groovy
androidTestImplementation 'androidx.test:runner:1.6.1' androidTestImplementation 'androidx.test:rules:1.6.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
Kotlin
androidTestImplementation('androidx.test:runner:1.6.1') androidTestImplementation('androidx.test:rules:1.6.1') androidTestImplementation('androidx.test.espresso:espresso-core:3.6.1')
常見的 API 用法
使用 Espresso 在 Android 上處理 WebView 時,onWebView()
方法是主要進入點。您可以使用這個方法執行 Espresso-Web 測試,例如:
Kotlin
onWebView() .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...)) .perform(webClick()) // Similar to perform(click()) // Similar to check(matches(...)) .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")))
Java
onWebView() .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...)) .perform(webClick()) // Similar to perform(click()) // Similar to check(matches(...)) .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")));
在本例中,Espresso-Web 會找出 ID 為 "link_2"
的 DOM 元素,然後點選該元素。然後,這項工具會驗證 WebView 是否傳送包含 "navigation_2.html"
字串的 GET 要求。
JavaScript 支援
執行測試時,系統會使用 JavaScript 執行所有 WebView 互動。因此,如要支援 JavaScript 評估,測試中的 WebView 必須啟用 JavaScript。
如要強制啟用 JavaScript,請在受測活動中呼叫 forceJavascriptEnabled()
做為 action,如以下程式碼片段所示。
@RunWith(AndroidJUnit4::class) class MyTestSuite { @get:Rule val activityScenarioRule = activityScenarioRule<MyWebViewActivity>() @Test fun testWebViewInteraction() { onWebView().forceJavascriptEnabled() } }
常見的網站互動
與 Web.WebInteraction
物件的常見互動包括:
-
withElement()
會參照 WebView 中的 DOM 元素。例子:
Kotlin
onWebView().withElement(findElement(Locator.ID, "teacher"))
Java
onWebView().withElement(findElement(Locator.ID, "teacher"));
-
withContextualElement()
參照 WebView 內相對於另一個 DOM 元素的範圍 DOM 元素。您應先呼叫withElement()
,建立參照Web.WebInteraction
物件 (DOM 元素)。例子:
Kotlin
.withElement(findElement(Locator.ID, "teacher")) .withContextualElement(findElement(Locator.ID, "person_name"))
Java
.withElement(findElement(Locator.ID, "teacher")) .withContextualElement(findElement(Locator.ID, "person_name"));
-
check()
會評估條件,確保條件解析為true
。例子:
Kotlin
onWebView() .withElement(findElement(Locator.ID, "teacher")) .withContextualElement(findElement(Locator.ID, "person_name")) .check(webMatches(getText(), containsString("Socrates")))
Java
onWebView() .withElement(findElement(Locator.ID, "teacher")) .withContextualElement(findElement(Locator.ID, "person_name")) .check(webMatches(getText(), containsString("Socrates")));
-
perform()
會在 WebView 中執行動作,例如點選元素。例子:
Kotlin
onWebView() .withElement(findElement(Locator.ID, "teacher")) .perform(webClick())
Java
onWebView() .withElement(findElement(Locator.ID, "teacher")) .perform(webClick());
-
reset()
會將 WebView 還原至初始狀態。如果先前的動作 (例如點擊) 導致導覽變更,使 ElementReference 和 WindowReference 物件無法存取,就必須執行這項操作。注意:雖然針對多頁面工作流程 (例如表單提交) 進行斷言時,使用
reset()
很有幫助,但測試範圍通常應有所限制,並著重於單一頁面。例子:
Kotlin
onWebView() .withElement(...) .perform(...) .reset()
Java
onWebView() .withElement(...) .perform(...) .reset();
範例
以下範例會測試在 WebView 中輸入文字並選取「Submit」按鈕後,相同文字是否會顯示在同一 WebView 的不同元素中:
Kotlin
const val MACCHIATO = "Macchiato" @RunWith(AndroidJUnit4::class) class MyEspressoWebTestSuite { @Test fun typeTextInInput_clickButton_SubmitsForm() { // Create an intent that displays a web form. val webFormIntent = Intent() // ... // Lazily launch the Activity with a custom start Intent per test. ActivityScenario.launchActivity(webFormIntent) // Selects the WebView in your layout. If you have multiple WebView // objects, you can also use a matcher to select a given WebView, // onWebView(withId(R.id.web_view)). onWebView() // Find the input element by ID. .withElement(findElement(Locator.ID, "text_input")) // Clear previous input and enter new text into the input element. .perform(clearElement()) .perform(DriverAtoms.webKeys(MACCHIATO)) // Find the "Submit" button and simulate a click using JavaScript. .withElement(findElement(Locator.ID, "submitBtn")) .perform(webClick()) // Find the response element by ID, and verify that it contains the // entered text. .withElement(findElement(Locator.ID, "response")) .check(webMatches(getText(), containsString(MACCHIATO))) } }
Java
public static final String MACCHIATO = "Macchiato"; @Test public void typeTextInInput_clickButton_SubmitsForm() { // Create an intent that displays a web form. Intent webFormIntent = new Intent(); // ... // Lazily launch the Activity with a custom start Intent per test. ActivityScenario.launchActivity(webFormIntent); // Selects the WebView in your layout. If you have multiple WebView objects, // you can also use a matcher to select a given WebView, // onWebView(withId(R.id.web_view)). onWebView() // Find the input element by ID. .withElement(findElement(Locator.ID, "text_input")) // Clear previous input and enter new text into the input element. .perform(clearElement()) .perform(DriverAtoms.webKeys(MACCHIATO)) // Find the "Submit" button and simulate a click using JavaScript. .withElement(findElement(Locator.ID, "submitBtn")) .perform(webClick()) // Find the response element by ID, and verify that it contains the // entered text. .withElement(findElement(Locator.ID, "response")) .check(webMatches(getText(), containsString(MACCHIATO))); }
其他資源
如要進一步瞭解如何在 Android 測試中使用 Espresso-Web,請參閱下列資源。
範例
- WebBasicSample:
使用 Espresso-Web 與
WebView
物件互動。