Controla tu app desde Macrobenchmark

A diferencia de la mayoría de las pruebas de IU de Android, las pruebas de Macrobenchmark se ejecutan en un proceso independiente de la app. Esto es necesario para habilitar acciones como detener el proceso de la app y compilar desde el código de bytes DEX hasta el código máquina.

Puedes controlar el estado de tu app con la biblioteca de UIAutomator o algún otro mecanismo que pueda controlar la app objetivo desde el proceso de prueba. Para exponer elementos de Compose a UI Automator, usa Modifier.testTag.

En el siguiente ejemplo, se usa un LazyColumn con un testTag:

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

La prueba usa el testTag para encontrar el LazyColumn y deslizarlo:

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

No es necesario que las comparativas se desplacen por la IU; En cambio, pueden ejecutar una animación, por ejemplo. Tampoco es necesario que usen específicamente UIAutomator. Recopilan métricas de rendimiento, siempre y cuando se produzcan fotogramas.

A veces, es posible que quieras comparar una pantalla específica que no sea visible de inmediato cuando se inicia la app, como una pantalla de detalles o una página de confirmación de la compra en lo profundo de tu gráfico de navegación de Jetpack.

Debido a que Macrobenchmark se ejecuta fuera del proceso, no puedes interactuar directamente con tu NavController para intercambiar pantallas. En cambio, tu comparativa debe simular que un usuario navega a esa parte de la app.

Usa el setupBlock para controlar los pasos de preparación, como hacer clic en un flujo de incorporación o en un botón de menú. De esta manera, tu measureBlock captura las métricas de rendimiento solo de la pantalla de destino.

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

Recursos adicionales

Para obtener más información sobre las pruebas, consulta los siguientes recursos.

Documentación

Contenido de Views