A differenza della maggior parte dei test dell'interfaccia utente di Android, i test Macrobenchmark vengono eseguiti in un processo separato dall'app stessa. Questo è necessario per abilitare funzionalità come l'interruzione del processo dell'app e la compilazione dal codice DEX al codice macchina.
Puoi decidere lo stato della tua app utilizzando la libreria UIAutomator o altri meccanismi che possono controllare l'app di destinazione dal processo di test.
Non puoi utilizzare Espresso o ActivityScenario
per
Macrobenchmark perché si aspetta che venga eseguito in un processo condiviso con l'app.
L'esempio seguente trova un elemento RecyclerView
che utilizza il suo ID risorsa e scorre diverse volte verso il basso:
Kotlin
@Test fun scrollList() { benchmarkRule.measureRepeated( // ... setupBlock = { // Before starting to measure, navigate to the UI to be measured val intent = Intent("$packageName.RECYCLER_VIEW_ACTIVITY") startActivityAndWait(intent) } ) { val recycler = device.findObject(By.res(packageName, "recycler")) // Set gesture margin to avoid triggering gesture navigation // with input events from automation. recycler.setGestureMargin(device.displayWidth / 5) // Scroll down several times repeat(3) { recycler.fling(Direction.DOWN) } } }
Java
@Test public void scrollList() { benchmarkRule.measureRepeated( // ... /* setupBlock */ scope -> { // Before measuring, navigate to the UI to be measured. val intent = Intent("$packageName.RECYCLER_VIEW_ACTIVITY") scope.startActivityAndWait(); return Unit.INSTANCE; }, /* measureBlock */ scope -> { UiDevice device = scope.getDevice(); UiObject2 recycler = device.findObject(By.res(scope.getPackageName(), "recycler")); // Set gesture margin to avoid triggering gesture navigation // with input events from automation. recycler.setGestureMargin(device.getDisplayWidth() / 5); // Fling the recycler several times. for (int i = 0; i < 3; i ) { recycler.fling(Direction.DOWN); } return Unit.INSTANCE; } ); }
Il benchmark non deve necessariamente scorrere nell'interfaccia utente. Ad esempio, può eseguire un'animazione. Inoltre, non deve utilizzare specificatamente l'automatizzatore UI. Raccoglie metriche sulle prestazioni finché i frame vengono prodotti dal sistema di visualizzazione, inclusi i frame generati da Jetpack Compose.
Andare alle parti interne dell'app
In alcuni casi è consigliabile eseguire il benchmarking di parti della tua app non accessibili direttamente dall'esterno. Potresti, ad esempio, accedere alle attività interne contrassegnate con exported=false
, accedere a una Fragment
o far scorrere alcune parti dell'interfaccia utente. I benchmark devono accedere manualmente a queste
parti dell'app come un utente.
Per navigare manualmente, modifica il codice all'interno di setupBlock{}
in modo che contenga l'effetto desiderato, ad esempio il tocco o lo scorrimento del pulsante. Il tuo measureBlock{}
contiene solo la manipolazione dell'UI a cui vuoi applicare il benchmark:
Kotlin
@Test fun nonExportedActivityScrollList() { benchmarkRule.measureRepeated( // ... setupBlock = setupBenchmark() ) { // ... } } private fun setupBenchmark(): MacrobenchmarkScope.() -> Unit = { // Before starting to measure, navigate to the UI to be measured startActivityAndWait() // click a button to launch the target activity. // While we use button text here to find the button, you could also use // accessibility info or resourceId. val selector = By.text("RecyclerView") if (!device.wait(Until.hasObject(selector), 5_500)) { fail("Could not find resource in time") } val launchRecyclerActivity = device.findObject(selector) launchRecyclerActivity.click() // wait until the activity is shown device.wait( Until.hasObject(By.clazz("$packageName.NonExportedRecyclerActivity")), TimeUnit.SECONDS.toMillis(10) ) }
Java
@Test public void scrollList() { benchmarkRule.measureRepeated( // ... /* setupBlock */ scope -> { // Before measuring, navigate to the default activity. scope.startActivityAndWait(); // Click a button to launch the target activity. // While you use resourceId here to find the button, you can also // use accessibility info or button text content. UiObject2 launchRecyclerActivity = scope.getDevice().findObject( By.res(packageName, "launchRecyclerActivity") ) launchRecyclerActivity.click(); // Wait until activity is shown. scope.getDevice().wait( Until.hasObject(By.clazz("$packageName.NonExportedRecyclerActivity")), 10000L ) return Unit.INSTANCE; }, /* measureBlock */ scope -> { // ... } ); }
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript non è attivo
- Scrivere un Macrobenchmark
- Acquisire metriche Macrobenchmark
- Microbenchmark