Mengontrol aplikasi dari Macrobenchmark

Tidak seperti kebanyakan pengujian UI Android, pengujian Macrobenchmark dijalankan dalam proses terpisah dari aplikasi itu sendiri. Hal ini diperlukan untuk memungkinkan tindakan seperti menghentikan proses aplikasi dan mengompilasi dari bytecode DEX ke kode mesin.

Anda dapat menjalankan status aplikasi menggunakan library UIAutomator atau mekanisme lain yang dapat mengontrol aplikasi target dari proses pengujian. Anda tidak dapat menggunakan Espresso atau ActivityScenario untuk Macrobenchmark karena harus dijalankan dalam proses bersama aplikasi.

Contoh berikut menemukan RecyclerView menggunakan ID resource-nya, dan men-scroll ke bawah beberapa kali:

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

Benchmark Anda tidak perlu men-scroll UI. Sebagai gantinya, benchmark dapat menjalankan animasi, misalnya. Benchmark juga tidak perlu menggunakan UI Automator secara khusus. Benchmark mengumpulkan metrik performa selama frame diproduksi oleh sistem tampilan, termasuk frame yang dihasilkan oleh Jetpack Compose.

Terkadang, Anda ingin membandingkan bagian-bagian aplikasi yang tidak dapat diakses langsung dari luar. Misalnya, mengakses Aktivitas internal yang ditandai dengan exported=false, menavigasi ke Fragment, atau menggeser beberapa bagian dari UI Anda. Benchmark perlu membuka bagian-bagian aplikasi ini secara manual seperti pengguna.

Untuk membuka secara manual, ubah kode di dalam setupBlock{} agar dapat memuat efek yang Anda inginkan, seperti ketuk tombol atau geser. measureBlock{} Anda hanya berisi manipulasi UI yang benar-benar ingin Anda ukur.

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 -> {
            // ...
        }
    );
}