برنامه خود را از Macrobenchmark کنترل کنید

برخلاف اکثر تست‌های رابط کاربری اندروید، تست‌های Macrobenchmark در فرآیندی جداگانه از خود برنامه اجرا می‌شوند. این برای فعال کردن مواردی مانند توقف فرآیند برنامه و کامپایل از بایت کد DEX به کد ماشین ضروری است.

می‌توانید وضعیت برنامه‌تان را با استفاده از کتابخانه UIAutomator یا مکانیسم‌های دیگری که می‌توانند برنامه هدف را از فرآیند آزمایش کنترل کنند، هدایت کنید. نمی‌توانید از Espresso یا ActivityScenario برای Macrobenchmark استفاده کنید، زیرا آنها انتظار دارند در یک فرآیند مشترک با برنامه اجرا شوند.

مثال زیر یک RecyclerView با استفاده از شناسه منبع آن پیدا می کند و چندین بار به پایین پیمایش می کند:

کاتلین

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

جاوا

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

معیار شما نیازی به اسکرول UI ندارد. در عوض، برای مثال، می تواند یک انیمیشن را اجرا کند. همچنین نیازی به استفاده خاص از UI Automator ندارد. تا زمانی که فریم‌ها توسط سیستم view تولید می‌شوند، معیارهای عملکرد را جمع‌آوری می‌کند، از جمله فریم‌های تولید شده توسط Jetpack Compose .

گاهی اوقات می خواهید بخش هایی از برنامه خود را که مستقیماً از خارج قابل دسترسی نیستند، معیار قرار دهید. این ممکن است برای مثال، دسترسی به فعالیت‌های داخلی که با exported=false علامت‌گذاری شده‌اند، پیمایش به Fragment ، یا کشیدن قسمتی از رابط کاربری خود به سمت بیرون باشد. معیارها باید به صورت دستی مانند یک کاربر به این بخش‌های برنامه حرکت کنند.

برای پیمایش دستی، کد داخل setupBlock{} را تغییر دهید تا جلوه مورد نظرتان را داشته باشد، مانند ضربه زدن روی دکمه یا کشیدن انگشت. measureBlock{} شما فقط شامل دستکاری رابط کاربری است که می‌خواهید واقعاً معیار قرار دهید:

کاتلین

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

جاوا

@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 -> {
            // ...
        }
    );
}
{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}