Compose 可與常見的測試架構整合。
與 Espresso 的互通性
在混合式應用程式中,您可以在檢視區塊階層中找到 Compose 元件,而在 Compose 可組合函式 (透過 AndroidView 可組合函式) 中找到檢視區塊。
這兩種類型不需要任何特殊步驟。您可以透過 Espresso 的 onView 比對檢視畫面,並透過 ComposeTestRule 比對 Compose 元素。
@Test
fun androidViewInteropTest() {
// Check the initial state of a TextView that depends on a Compose state.
Espresso.onView(withText("Hello Views")).check(matches(isDisplayed()))
// Click on the Compose button that changes the state.
composeTestRule.onNodeWithText("Click here").performClick()
// Check the new value.
Espresso.onView(withText("Hello Compose")).check(matches(isDisplayed()))
}
為 Compose 互通性測試新增 View 範圍的語意
將 Compose 搜尋範圍限定在特定檢視畫面
將複雜的 UI 遷移至 Compose 時,您可能會遇到巢狀結構的相同 Compose 元素,位於多個傳統 Android 檢視區塊內,例如 RecyclerView 或 ViewPager 內。在這些情況下,標準的 Compose 搜尋 (例如 onNodeWithText("Save")) 可能會失敗,並顯示「找到多個節點」錯誤。
您不必修改正式版程式碼來插入動態測試標記,以區分這些元素,可以直接將 Compose 測試範圍限定在特定 Android 檢視區塊。
在測試規則中使用 onRootWithViewInteraction API。這個函式會接受 Espresso ViewInteraction,讓您運用 Espresso 隔離特定容器檢視區塊,並僅在該範圍階層中執行 Compose 互動。
與清單項目互動
如要與特定 RecyclerView 資料列內的 Compose 元素互動,請使用 Espresso 找出該資料列,然後將 Compose 互動範圍限定於該資料列。這會忽略所有其他資料列中相同的 Compose 元素。
@Test fun testComposeButtonInsideRecyclerViewItem() = runComposeUiTest { // Scroll to the desired position using Espresso Espresso.onView(withId(recyclerViewId)) .perform(RecyclerViewActions.scrollToPosition<MyViewHolder>(3)) // Define an Espresso ViewInteraction that uniquely identifies the row val rowView = Espresso.onView( allOf( withId(rootViewId), hasDescendant(withText("Item #3")) ) ) // Scope the Compose search strictly to that specific row View onRootWithViewInteraction(rowView) .onNode(hasText("Like")) .performClick() }
解決 ViewPager 中的模糊不清問題
如果記憶體中同時有多個具有相同 Compose 版面配置的片段,您可以將搜尋範圍限定在特定片段的根檢視區塊 ID,避免比對結果模稜兩可。
@Test fun testComposeButtonInsideViewPagerItem() = runComposeUiTest { // Swipe to the desired page using Espresso Espresso.onView(withId(viewPagerViewId)).perform(swipeLeft()) // Identify the specific container view using Espresso val fragmentB = Espresso.onView(withId(fragmentRootViewId)) // The generic text "Save" is now unique within this view scope onRootWithViewInteraction(fragmentB) .onNode(hasText("Save")) .assertIsDisplayed() }
與 UiAutomator 的互通性
可組合項預設只能用其便利描述項 (顯示文字、內容說明等等) 才能從 UiAutomator 存取。如要存取任何使用 Modifier.testTag 的可組合項,則需為特定可組合項的子樹狀結構啟用語意屬性 testTagsAsResourceId。如果可組合項並無其他任何專屬控制代碼,例如捲動式可組合項 (例如:LazyColumn),啟用這項行為會非常實用。
您只能在可組合項階層達到高時才能啟用語意屬性,以便確保所有設有 Modifier.testTag 的巢狀結構可組合項都可以從 UiAutomator 存取。
Scaffold(
// Enables for all composables in the hierarchy.
modifier = Modifier.semantics {
testTagsAsResourceId = true
}
){
// Modifier.testTag is accessible from UiAutomator for composables nested here.
LazyColumn(
modifier = Modifier.testTag("myLazyColumn")
){
// Content
}
}
任何設有 Modifier.testTag(tag) 的可組合項都可以藉由使用 By.res(resourceName) 並利用相同的 tag 做為 resourceName 的方式存取。
val device = UiDevice.getInstance(getInstrumentation())
val lazyColumn: UiObject2 = device.findObject(By.res("myLazyColumn"))
// Some interaction with the lazyColumn.
其他資源
- 在 Android 上測試應用程式:這個主要的 Android 測試到達網頁,提供更廣泛的測試基礎知識和技術。
- 測試基礎知識:進一步瞭解測試 Android 應用程式背後的概念。
- 本機測試:您可以在自己的工作站上,在本機執行部分測試。
- 檢測設備測試:建議您也執行檢測設備測試。也就是直接在裝置端執行的測試。
- 持續整合: 持續整合可讓您將測試整合至部署管道。
- 測試不同螢幕大小:使用者可選擇的裝置種類繁多,因此您應測試不同螢幕大小。
- Espresso:雖然 Espresso 是專為以 View 為基礎的 UI 設計,但您仍可運用相關知識,進行部分 Compose 測試。