Contrairement à la plupart des tests de l'interface utilisateur Android, les tests Macrobenchmark s'exécutent dans un processus distinct de l'appli elle-même. Cela est nécessaire pour permettre, entre autres, d'arrêter le processus de l'application et de compiler du bytecode DEX en code machine.
Vous pouvez contrôler l'état de votre application à l'aide de la bibliothèque UIAutomator ou d'autres
mécanismes pouvant contrôler l'application cible à partir du processus de test.
Pour exposer les éléments Compose à UIAutomator, utilisez Modifier.testTag.
L'exemple suivant utilise un LazyColumn avec un testTag :
@Composable
fun ProductListScreen() {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.testTag("my_lazy_column") ) {
items(100) { index ->
ProductItem(index)
}
}
}
Le test utilise le testTag pour rechercher le LazyColumn et le faire glisser d'un geste vif :
@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)
}
}
}
}
Votre benchmark n'a pas besoin de faire défiler l'interface utilisateur. À la place, il peut par exemple exécuter une animation. Il n'a pas non plus besoin d'utiliser UIAutomator en particulier. Il collecte des métriques de performances tant que les frames sont produits.
Accéder à des destinations composables profondes
Vous pouvez parfois avoir besoin de comparer les performances d'un écran spécifique qui n'est pas immédiatement visible au démarrage de l'application, comme un écran de détails ou une page de paiement située en profondeur dans votre graphe de navigation Jetpack.
Étant donné que Macrobenchmark s'exécute hors processus, vous ne pouvez pas interagir directement avec votre NavController pour changer d'écran. Votre benchmark doit plutôt simuler un utilisateur accédant à cette partie de l'application.
Utilisez le setupBlock pour gérer les étapes de préparation, comme cliquer sur un flux d'intégration ou un bouton de menu. De cette façon, votre measureBlock ne capture que les métriques de performances de l'écran cible.
@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)
}
}
}
Ressources supplémentaires
Pour en savoir plus sur les tests, consultez les ressources suivantes.
Documentation
Afficher le contenu
Recommandations personnalisées
- Remarque : Le texte du lien s'affiche lorsque JavaScript est désactivé
- Écrire un macrobenchmark
- Capturer les métriques Macrobenchmark
- Microbenchmark