透過 Macrobenchmark 控制應用程式

與大多數 Android UI 測試不同,Macrobenchmark 測試會在應用程式本身以外的程序中執行。對於停止應用程式處理程序及從 DEX 位元碼編譯至機器碼等操作,上述作法是必要的。

您可以使用 UIAutomator 程式庫,或透過測試程序控制目標應用程式,驅動應用程式狀態。如要向 UI Automator 公開 Compose 元素,請使用 Modifier.testTag

以下範例使用 LazyColumntestTag

@Composable
fun ProductListScreen() {
    LazyColumn(
        modifier = Modifier
            .fillMaxSize()
            .testTag("my_lazy_column")    ) {
        items(100) { index ->
            ProductItem(index)
        }
    }
}

這項測試會使用 testTag 找出 LazyColumn 並快速滑過:

@Test
fun scrollList() {
    benchmarkRule.measureRepeated(
        packageName = "com.example.myapp",
        metrics = listOf(FrameTimingMetric()),
        iterations = 5,
        setupBlock = {
            uiAutomator {
                pressHome()
                startApp("com.example.myapp")
            }
        }
    ) {
        uiAutomator {
            // Find the Composable using its testTag mapped as a viewIdResourceName
            val lazyColumn = onElement { viewIdResourceName == "my_lazy_column" }

            // Fling the Compose list down
            repeat(3) {
                lazyColumn.fling(Direction.DOWN)
            }
        }
    }
}

效能評定不一定要捲動 UI。舉例來說,可以改為執行動畫。這也不需要特別使用 UI Automator,只要畫面是由系統產生,系統就會收集成效指標。

有時您可能想對應用程式啟動時不會立即顯示的特定畫面進行基準化,例如 Jetpack Navigation 圖表中的詳細資料畫面或結帳頁面。

由於 Macrobenchmark 是在程序外執行,因此您無法直接與 NavController 互動來切換畫面。基準測試必須模擬使用者前往應用程式該部分的動作。

使用 setupBlock 處理準備步驟,例如點選新手上路流程或選單按鈕。這樣一來,measureBlock 就只會擷取目標畫面的成效指標。

@Test
fun deepScreenScrollList() {
    benchmarkRule.measureRepeated(
        packageName = "com.example.myapp",
        metrics = listOf(FrameTimingMetric()),
        iterations = 5,
        setupBlock = {
            uiAutomator {
                // 1. Start the app on the home screen
                startApp("com.example.myapp")

                // 2. Navigate to the internal screen by clicking a Compose component
                // (e.g., a card that opens the target list view)
                val settingsButton = onElement { viewIdResourceName == "go_to_list_button" }
                settingsButton.click()

                // 3. Wait until the target screen settles and is fully rendered
                waitForStableInActiveWindow()
            }
        }
    ) {
        uiAutomator {
            // The actual benchmark measurement starts here on the target screen
            val lazyColumn = onElement { viewIdResourceName == "my_lazy_column" }
            lazyColumn.fling(Direction.DOWN)
        }
    }
}

其他資源

如要進一步瞭解測試,請參閱下列資源。

說明文件

Views content