您可以使用完善的方法和模式測試 Compose 應用程式。
獨立測試
ComposeTestRule 可讓您啟動顯示任何可組合項的活動:完整應用程式、單一畫面或小型元素。同時也建議您檢查可組合的元件是否封裝正確,且可單獨進行,以便針對更焦點且更易於執行的 UI 測試。
這不代表只能建立單元 UI 測試。對 UI 中範圍較大的部分進行的測試也同樣重要。
設定自己的內容後存取活動和資源
您通常需要使用 composeTestRule.setContent 設定要測試的內容,也需要存取活動資源,例如聲明宣告的文字與字串資源相符。不過,如果活動已經呼叫 setContent,您無法再為使用 createAndroidComposeRule() 建立的規則呼叫它。
為此,常見的模式是使用空白活動 (例如 ComponentActivity) 建立 AndroidComposeTestRule。
class MyComposeTest {
@get:Rule
val composeTestRule = createAndroidComposeRule<ComponentActivity>()
@Test
fun myTest() {
// Start the app
composeTestRule.setContent {
MyAppTheme {
MainScreen(uiState = exampleUiState, /*...*/)
}
}
val continueLabel = composeTestRule.activity.getString(R.string.next)
composeTestRule.onNodeWithText(continueLabel).performClick()
}
}
請注意,您必須在應用程式的 AndroidManifest.xml 檔案中新增 ComponentActivity。如要啟用這項功能,請將這個依附元件新增至模組:
debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version")
自訂語意屬性
您可以建立自訂元件資訊屬性,向測試對象顯示資訊。做法是定義新的 SemanticsPropertyKey,並透過 SemanticsPropertyReceiver 提供。
// Creates a semantics property of type Long.
val PickedDateKey = SemanticsPropertyKey<Long>("PickedDate")
var SemanticsPropertyReceiver.pickedDate by PickedDateKey
現在,請在 semantics 修飾符中使用該屬性:
val datePickerValue by remember { mutableStateOf(0L) }
MyCustomDatePicker(
modifier = Modifier.semantics { pickedDate = datePickerValue }
)
透過測試,您可以使用 SemanticsMatcher.expectValue 聲明屬性的值:
composeTestRule
.onNode(SemanticsMatcher.expectValue(PickedDateKey, 1445378400)) // 2015-10-21
.assertExists()
驗證狀態還原
重新建立活動或程序後,請確認 Compose 元素的狀態是否已順利還原。您可以直接使用 StateRestorationTester 類別執行這類檢查,而不必依賴重新建立活動。
這個類別可讓您模擬可組合項的重新建立。請務必驗證 rememberSaveable 的實作方式。
class MyStateRestorationTests {
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun onRecreation_stateIsRestored() {
val restorationTester = StateRestorationTester(composeTestRule)
restorationTester.setContent { MainScreen() }
// TODO: Run actions that modify the state
// Trigger a recreation
restorationTester.emulateSavedInstanceStateRestore()
// TODO: Verify that state has been correctly restored.
}
}
測試不同的裝置設定
Android 應用程式必須適應許多變化條件,例如視窗大小、地區設定、字型大小、深色和淺色主題等。這些條件大多衍生自使用者控制的裝置層級值,並透過目前的 Configuration 執行個體公開。由於測試必須設定裝置層級的屬性,因此很難直接在測試中測試不同設定。
DeviceConfigurationOverride 是僅供測試的 API,可讓您以本地化方式模擬受測 @Composable 內容的不同裝置設定。
DeviceConfigurationOverride 的伴隨物件具有下列擴充功能函式,可覆寫裝置層級的設定屬性:
DeviceConfigurationOverride.DarkMode():覆寫系統設定,改用深色或淺色主題。DeviceConfigurationOverride.FontScale():覆寫系統字型比例。DeviceConfigurationOverride.FontWeightAdjustment():覆寫系統字型粗細調整設定。DeviceConfigurationOverride.ForcedSize():無論裝置大小為何,都會強制使用特定大小的空間。DeviceConfigurationOverride.LayoutDirection():覆寫版面配置方向 (從左到右或從右到左)。DeviceConfigurationOverride.Locales():覆寫 locale。DeviceConfigurationOverride.RoundScreen():如果螢幕是圓形,則會覆寫。
如要套用特定覆寫值,請在呼叫 DeviceConfigurationOverride() 頂層函式時,將要套用的覆寫值做為參數傳遞,並將受測內容包裝在該函式中。
舉例來說,以下程式碼會套用 DeviceConfigurationOverride.ForcedSize() 覆寫,在本機變更密度,強制在大型橫向視窗中轉譯 MyScreen 可組合項,即使測試執行的裝置不直接支援該視窗大小也一樣:
composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp)) ) { MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping. } }
如要一併套用多個覆寫值,請使用 DeviceConfigurationOverride.then():
composeTestRule.setContent { DeviceConfigurationOverride( DeviceConfigurationOverride.FontScale(1.5f) then DeviceConfigurationOverride.FontWeightAdjustment(200) ) { Text(text = "text with increased scale and weight") } }
在測試中自訂失敗處理方式
偵錯 UI 測試時,如果斷言失敗,通常需要檢查畫面狀態和組合階層。
Compose 提供原生錯誤處理管道,可簡化診斷程序。您可以在失敗時自動擷取螢幕截圖和 UI 階層,也可以註冊自訂處理常式,將當機遙測資料轉送至外部工具。
設定故障處理
如要設定失敗處理方式,請將 TestFailurePolicy 物件傳遞至 ComposeUiTestConfig。
擷取內建失敗構件
如要在測試失敗時擷取螢幕截圖和 UI 層級,請在 TestFailurePolicy 中設定 screenshotCaptureMode 和 uiHierarchyCaptureMode 屬性。
class MyComposeTest { private val customConfig = ComposeUiTestConfig( failurePolicy = TestFailurePolicy( screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled, uiHierarchyCaptureMode = TestFailurePolicy.CaptureMode.Enabled ) ) @Test fun myFirstTest() = runComposeUiTest(config = customConfig) { // ... } }
使用自訂失敗處理常式
如要為測試失敗定義自訂行為,請將 TestFailureHandler 新增至 failureHandlers 清單。每個處理常式都會收到 FailureContext 物件,其中包含原始錯誤和先前管道處理常式產生的構件清單。
class MyComposeTestWithHandler { private val customConfig = ComposeUiTestConfig( failurePolicy = TestFailurePolicy( screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled, failureHandlers = listOf( TestFailureHandler { context -> val screenshot = context.artifacts.firstOrNull { it.type == FailureArtifact.Type.Screenshot } // ... } ) ) ) @get:Rule val rule = createComposeRule(config = customConfig) // ... }
為整個測試套件設定擷取畫面
如要為整個測試套件啟用失敗構件擷取功能,請在模組的 build.gradle 檔案中傳遞插樁測試執行器引數。這樣就不必更新個別測試檔。
// build.gradle.kts
android {
defaultConfig {
// ...
testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isUiHierarchyCaptureEnabled"] = "true"
testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isScreenshotCaptureEnabled"] = "true"
}
}
設定優先順序
這個架構會評估本機 TestFailurePolicy 和套件層級的執行器引數:
- 如果您在測試
failurePolicy中明確將模式設為CaptureMode.Enabled/Disabled,這會覆寫執行器引數。 - 如果將模式設為
CaptureMode.Unspecified(或將failurePolicy留為null),架構會回復為執行器引數。
其他資源
- 在 Android 上測試應用程式:這個主要的 Android 測試到達網頁,提供更廣泛的測試基礎知識和技術。
- 測試基礎知識:進一步瞭解測試 Android 應用程式背後的概念。
- 本機測試:您可以在自己的工作站上,在本機執行部分測試。
- 檢測設備測試:建議您也執行檢測設備測試。也就是直接在裝置端執行的測試。
- 持續整合: 持續整合可讓您將測試整合至部署管道。
- 測試不同螢幕大小:使用者可選擇的裝置種類繁多,因此您應測試不同螢幕大小。
- Espresso:雖然 Espresso 是專為以 View 為基礎的 UI 設計,但您仍可運用相關知識,測試 Compose 的某些層面。