App über MacroBenchmark steuern

Im Gegensatz zu den meisten Android-UI-Tests werden Makrobenchmark-Tests in einem separaten Prozess von der App selbst ausgeführt. Dies ist erforderlich, um beispielsweise den App-Prozess zu beenden und DEX-Bytecode in Maschinencode zu kompilieren.

Sie können den Status Ihrer App mit der UIAutomator-Bibliothek oder anderen Mechanismen steuern, mit denen die Ziel-App über den Testprozess gesteuert werden kann. Verwenden Sie Modifier.testTag, um Compose-Elemente für UI Automator verfügbar zu machen.

Im folgenden Beispiel wird ein LazyColumn mit einem testTag verwendet:

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

Im Test wird die testTag verwendet, um die LazyColumn zu finden und zu übertragen:

@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)
            }
        }
    }
}

Ihr Benchmark muss nicht durch die Benutzeroberfläche scrollen. Stattdessen kann beispielsweise eine Animation ausgeführt werden. Es muss auch nicht speziell UI Automator verwendet werden. Leistungsmesswerte werden erfasst, solange Frames gerendert werden.

Manchmal möchten Sie einen bestimmten Bildschirm testen, der beim Start der App nicht sofort sichtbar ist, z. B. einen Detailbildschirm oder eine Zahlungsseite, die sich tief in Ihrem Jetpack Navigation-Graphen befindet.

Da Makrobenchmarks außerhalb des Prozesses ausgeführt werden, können Sie nicht direkt mit Ihrem NavController interagieren, um Bildschirme zu wechseln. Stattdessen muss Ihr Benchmark simulieren, dass ein Nutzer zu diesem Teil der App navigiert.

Verwenden Sie setupBlock für die Vorbereitungsschritte, z. B. das Klicken durch einen Onboarding-Ablauf oder auf eine Menüschaltfläche. So werden in measureBlock nur die Leistungsmesswerte des Zielbildschirms erfasst.

@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)
        }
    }
}

Zusätzliche Ressourcen

Weitere Informationen zum Testen finden Sie in den folgenden Ressourcen.

Dokumentation

Inhalte ansehen