ควบคุมแอปจากการเปรียบเทียบแบบมาโคร

การทดสอบ Macrobenchmark จะทำงานในกระบวนการแยกจากแอปเอง ซึ่งแตกต่างจากการทดสอบ UI ของ Android ส่วนใหญ่ จำเป็นต้องทำเช่นนี้เพื่อให้สามารถดำเนินการต่างๆ ได้ เช่น หยุดกระบวนการของแอปและคอมไพล์จากไบต์โค้ด DEX เป็นรหัสเครื่อง

คุณสามารถควบคุมสถานะของแอปได้โดยใช้ไลบรารี UIAutomator หรือ กลไกอื่นๆ ที่ควบคุมแอปเป้าหมายจากกระบวนการทดสอบได้ หากต้องการแสดงองค์ประกอบ Compose ให้ UI Automator ให้ใช้ Modifier.testTag

ตัวอย่างต่อไปนี้ใช้ LazyColumn ที่มี testTag

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

แหล่งข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมเกี่ยวกับการทดสอบได้ที่แหล่งข้อมูลต่อไปนี้

เอกสารประกอบ

ดูเนื้อหา