Macrobenchmark에서 앱 제어

대부분의 Android UI 테스트와 달리 Macrobenchmark 테스트는 앱 자체와 분리된 프로세스에서 실행됩니다. 이는 앱 프로세스를 중지하고 DEX 바이트 코드를 기계어 코드로 컴파일하는 등의 작업을 위해 필요합니다.

UIAutomator 라이브러리를 사용하거나 테스트 프로세스에서 타겟 앱을 제어할 수 있는 다른 메커니즘을 사용하여 앱 상태를 유도할 수 있습니다. Compose 요소를 UI Automator에 노출하려면 Modifier.testTag를 사용하세요.

다음 예시에서는 testTag과 함께 LazyColumn를 사용합니다.

@Composable
fun ProductListScreen() {
    LazyColumn(
        modifier = Modifier
            .fillMaxSize()
            .testTag("my_lazy_column")    ) {
        items(100) { index ->
            ProductItem(index)
        }
    }
}

테스트에서는 testTag를 사용하여 LazyColumn를 찾아 살짝 튕깁니다.

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

벤치마크에서는 UI를 스크롤하지 않아도 됩니다. 대신 애니메이션 등을 실행할 수 있습니다. 또한 UI Automator를 특별히 사용할 필요가 없습니다. 프레임이 생성되는 한 성능 측정항목이 수집됩니다.

앱이 시작될 때 바로 표시되지 않는 특정 화면(예: Jetpack 탐색 그래프 내의 세부정보 화면 또는 결제 페이지)을 벤치마킹해야 할 때도 있습니다.

Macrobenchmark는 프로세스 외부에서 실행되므로 NavController와 직접 상호작용하여 화면을 전환할 수 없습니다. 대신 벤치마크는 사용자가 앱의 해당 부분으로 이동하는 것을 시뮬레이션해야 합니다.

setupBlock를 사용하여 온보딩 흐름이나 메뉴 버튼을 클릭하는 등의 준비 단계를 처리합니다. 이렇게 하면 measureBlock가 타겟 화면의 성능 측정항목만 캡처합니다.

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

추가 리소스

테스트에 관한 자세한 내용은 다음 리소스를 참고하세요.

문서

콘텐츠 보기