Controlar o app usando a Macrobenchmark

Diferente da maioria dos testes de interface do Android, os testes da Macrobenchmark acontecem em um processo separado do próprio app. Isso é necessário para ativar ações como interromper o processo do app e compilar o bytecode DEX para um código de máquina.

Você pode controlar o estado do app usando a biblioteca UIAutomator ou outros mecanismos que podem controlar o app de destino do processo de teste. Para expor elementos do Compose ao UI Automator, use Modifier.testTag.

testTagsAsResourceIdtrue

O exemplo a seguir usa uma LazyColumn com uma testTag:

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

O teste usa a testTag para encontrar a LazyColumn e lançá-la:

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

A comparação não precisa rolar a interface. Em vez disso, ela pode gerar uma animação, por exemplo. Ela também não precisa usar a biblioteca UI Automator especificamente. As métricas de performance são coletadas, contanto que os frames estejam sendo produzidos.

Às vezes, você pode querer comparar uma tela específica que não fica visível imediatamente quando o app é iniciado, como uma tela de detalhes ou uma página de finalização da compra no gráfico de navegação do Jetpack.

Como a Macrobenchmark é executada fora do processo, não é possível interagir diretamente com o NavController para trocar de tela. Em vez disso, a comparação precisa simular um usuário navegando até essa parte do app.

Use o setupBlock para processar as etapas de preparação, como clicar em um fluxo de integração ou em um botão de menu. Dessa forma, o measureBlock captura as métricas de performance apenas da tela 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)
        }
    }
}

Outros recursos

Para mais informações sobre testes, consulte os seguintes recursos.

Documentação

Conteúdo de visualizações