A differenza della maggior parte dei test dell'interfaccia utente di Android, i test di Macrobenchmark vengono eseguiti in un processo separato dall'app stessa. Questo è necessario per abilitare operazioni come l'arresto del processo dell'app e la compilazione dal bytecode DEX al codice macchina.
Puoi controllare lo stato dell'app utilizzando la libreria UIAutomator o altri
meccanismi in grado di controllare l'app di destinazione dal processo di test.
Per esporre gli elementi Compose a UI Automator, utilizza Modifier.testTag.
L'esempio seguente utilizza un LazyColumn con un testTag:
@Composable
fun ProductListScreen() {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.testTag("my_lazy_column") ) {
items(100) { index ->
ProductItem(index)
}
}
}
Il test utilizza testTag per trovare LazyColumn e lanciarlo:
@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)
}
}
}
}
Il benchmark non deve necessariamente scorrere l'interfaccia utente. Può invece eseguire un'animazione, ad esempio. Inoltre, non è necessario utilizzare UI Automator in modo specifico. Raccoglie le metriche sul rendimento finché vengono prodotti frame.
Navigare verso destinazioni componibili profonde
A volte potresti voler eseguire il benchmark di una schermata specifica che non è immediatamente visibile all'avvio dell'app, ad esempio una schermata dei dettagli o una pagina di pagamento all'interno del grafico di navigazione di Jetpack.
Poiché Macrobenchmark viene eseguito fuori processo, non puoi interagire direttamente con NavController per scambiare le schermate. Il benchmark deve invece simulare un utente che naviga verso quella parte dell'app.
Utilizza setupBlock per gestire i passaggi di preparazione, ad esempio facendo clic su un flusso di onboarding o su un pulsante del menu. In questo modo, measureBlock acquisisce le metriche sul rendimento solo della schermata di destinazione.
@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)
}
}
}
Risorse aggiuntive
Per ulteriori informazioni sui test, consulta le seguenti risorse.
Documentazione
Visualizzare i contenuti
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Scrivere un Macrobenchmark
- Acquisire le metriche di Macrobenchmark
- Microbenchmark