รูปแบบทั่วไป

คุณทดสอบแอป Compose ได้ด้วยแนวทางและรูปแบบที่ได้รับการยอมรับ

ทดสอบแบบแยก

ComposeTestRule ช่วยให้คุณเริ่มกิจกรรมที่แสดง Composable ใดก็ได้ ไม่ว่าจะเป็น แอปพลิเคชันทั้งหมด หน้าจอเดียว หรือองค์ประกอบเล็กๆ นอกจากนี้ การตรวจสอบว่า Composable ได้รับการแคปซูลอย่างถูกต้องและทำงานได้อย่างอิสระยังเป็นแนวทางปฏิบัติที่ดี ซึ่งจะช่วยให้การทดสอบ UI ง่ายขึ้นและมีประสิทธิภาพมากขึ้น

แต่ไม่ได้หมายความว่าคุณควรสร้างการทดสอบ UI หน่วยเท่านั้น การกำหนดขอบเขตการทดสอบ UI ส่วนที่ใหญ่ขึ้นของ UI ก็มีความสำคัญมากเช่นกัน

เข้าถึงกิจกรรมและแหล่งข้อมูลหลังจากตั้งค่าเนื้อหาของคุณเอง

บ่อยครั้งที่คุณต้องตั้งค่าเนื้อหาภายใต้การทดสอบโดยใช้ composeTestRule.setContent และคุณยังต้องเข้าถึงทรัพยากรกิจกรรมด้วย เช่น เพื่อยืนยันว่าข้อความที่แสดงตรงกับทรัพยากรสตริง อย่างไรก็ตาม คุณ จะเรียกใช้ setContent ในกฎที่สร้างด้วย createAndroidComposeRule() ไม่ได้ หาก กิจกรรมเรียกใช้กฎดังกล่าวอยู่แล้ว

รูปแบบทั่วไปในการดำเนินการนี้คือการสร้าง AndroidComposeTestRule โดยใช้ กิจกรรมที่ว่างเปล่า เช่น ComponentActivity

class MyComposeTest {

    @get:Rule
    val composeTestRule = createAndroidComposeRule<ComponentActivity>()

    @Test
    fun myTest() {
        // Start the app
        composeTestRule.setContent {
            MyAppTheme {
                MainScreen(uiState = exampleUiState, /*...*/)
            }
        }
        val continueLabel = composeTestRule.activity.getString(R.string.next)
        composeTestRule.onNodeWithText(continueLabel).performClick()
    }
}

โปรดทราบว่าคุณต้องเพิ่ม ComponentActivity ลงในไฟล์ AndroidManifest.xml ของแอป โดยเปิดใช้ได้ด้วยการเพิ่มทรัพยากร Dependency นี้ลงในโมดูล

debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version")

พร็อพเพอร์ตี้ความหมายที่กำหนดเอง

คุณสามารถสร้างพร็อพเพอร์ตี้ความหมายที่กำหนดเองเพื่อแสดงข้อมูลในการทดสอบ โดยให้กำหนด SemanticsPropertyKey ใหม่และทำให้พร้อมใช้งานโดยใช้ SemanticsPropertyReceiver

// Creates a semantics property of type Long.
val PickedDateKey = SemanticsPropertyKey<Long>("PickedDate")
var SemanticsPropertyReceiver.pickedDate by PickedDateKey

ตอนนี้ให้ใช้พร็อพเพอร์ตี้นั้นในตัวแก้ไข semantics ดังนี้

val datePickerValue by remember { mutableStateOf(0L) }
MyCustomDatePicker(
    modifier = Modifier.semantics { pickedDate = datePickerValue }
)

จากการทดสอบ ให้ใช้ SemanticsMatcher.expectValue เพื่อยืนยันค่าของพร็อพเพอร์ตี้

composeTestRule
    .onNode(SemanticsMatcher.expectValue(PickedDateKey, 1445378400)) // 2015-10-21
    .assertExists()

ยืนยันการคืนค่าสถานะ

ตรวจสอบว่าระบบได้กู้คืนสถานะขององค์ประกอบ Compose อย่างถูกต้องเมื่อสร้างกิจกรรมหรือกระบวนการขึ้นมาใหม่ ทําการตรวจสอบดังกล่าวโดยไม่ต้องอาศัยการสร้างกิจกรรมใหม่ด้วยคลาส StateRestorationTester

คลาสนี้ช่วยให้คุณจำลองการสร้าง Composable ขึ้นมาใหม่ได้ โดยเฉพาะอย่างยิ่ง มีประโยชน์ในการยืนยันการติดตั้งใช้งาน rememberSaveable


class MyStateRestorationTests {

    @get:Rule
    val composeTestRule = createComposeRule()

    @Test
    fun onRecreation_stateIsRestored() {
        val restorationTester = StateRestorationTester(composeTestRule)

        restorationTester.setContent { MainScreen() }

        // TODO: Run actions that modify the state

        // Trigger a recreation
        restorationTester.emulateSavedInstanceStateRestore()

        // TODO: Verify that state has been correctly restored.
    }
}

ทดสอบการกำหนดค่าอุปกรณ์ต่างๆ

แอป Android ต้องปรับให้เข้ากับเงื่อนไขที่เปลี่ยนแปลงไปมากมาย เช่น ขนาดหน้าต่าง ภาษา ขนาดแบบอักษร ธีมมืดและสว่าง และอื่นๆ เงื่อนไขส่วนใหญ่เหล่านี้ได้มาจากค่าระดับอุปกรณ์ที่ผู้ใช้ควบคุมและแสดงด้วยอินสแตนซ์ Configuration ปัจจุบัน การทดสอบการกำหนดค่าที่แตกต่างกัน ในการทดสอบโดยตรงเป็นเรื่องยากเนื่องจากการทดสอบต้องกำหนดค่าพร็อพเพอร์ตี้ระดับอุปกรณ์

DeviceConfigurationOverride เป็น API สำหรับการทดสอบเท่านั้นที่ช่วยให้คุณจำลอง การกำหนดค่าอุปกรณ์ต่างๆ ในลักษณะที่แปลเป็นภาษาท้องถิ่นสำหรับเนื้อหา @Composable ที่อยู่ระหว่างการทดสอบได้

ออบเจ็กต์คู่ของ DeviceConfigurationOverride มีฟังก์ชันส่วนขยายต่อไปนี้ ซึ่งจะลบล้างพร็อพเพอร์ตี้การกำหนดค่าระดับอุปกรณ์

หากต้องการใช้การลบล้างที่เฉพาะเจาะจง ให้รวมเนื้อหาภายใต้การทดสอบไว้ในการเรียกฟังก์ชันระดับบนสุดของ DeviceConfigurationOverride() โดยส่งการลบล้าง ที่จะใช้เป็นพารามิเตอร์

ตัวอย่างเช่น โค้ดต่อไปนี้ใช้DeviceConfigurationOverride.ForcedSize()การลบล้างเพื่อเปลี่ยนความหนาแน่น ในเครื่อง ซึ่งบังคับให้แสดงผล MyScreen Composable ในหน้าต่างแนวนอนขนาดใหญ่ แม้ว่าอุปกรณ์ที่ใช้ทดสอบจะไม่รองรับขนาดหน้าต่างนั้นโดยตรงก็ตาม

composeTestRule.setContent {
    DeviceConfigurationOverride(
        DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp))
    ) {
        MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping.
    }
}

หากต้องการใช้การลบล้างหลายรายการพร้อมกัน ให้ใช้ DeviceConfigurationOverride.then() ดังนี้

composeTestRule.setContent {
    DeviceConfigurationOverride(
        DeviceConfigurationOverride.FontScale(1.5f) then
            DeviceConfigurationOverride.FontWeightAdjustment(200)
    ) {
        Text(text = "text with increased scale and weight")
    }
}

การจัดการข้อผิดพลาดที่กำหนดเองในการทดสอบ

การแก้ไขข้อบกพร่องของการทดสอบ UI มักต้องตรวจสอบสถานะหน้าจอและลำดับชั้นขององค์ประกอบ เมื่อการยืนยันล้มเหลว

Compose มีไปป์ไลน์การจัดการข้อผิดพลาดดั้งเดิมเพื่อเพิ่มประสิทธิภาพการวินิจฉัย คุณสามารถจับภาพหน้าจอและลำดับชั้น UI โดยอัตโนมัติเมื่อเกิดข้อผิดพลาด หรือ ลงทะเบียนตัวแฮนเดิลที่กำหนดเองเพื่อส่งต่อข้อมูลการวัดระยะการขัดข้องไปยังเครื่องมือภายนอก

กำหนดค่าการจัดการความล้มเหลว

หากต้องการกำหนดค่าการจัดการข้อผิดพลาด ให้ส่งออบเจ็กต์ TestFailurePolicy ไปยัง ComposeUiTestConfig

บันทึกอาร์ติแฟกต์ข้อขัดข้องในตัว

หากต้องการบันทึกภาพหน้าจอและลําดับชั้น UI เมื่อการทดสอบล้มเหลว ให้ตั้งค่าพร็อพเพอร์ตี้ screenshotCaptureMode และ uiHierarchyCaptureMode ใน TestFailurePolicy

class MyComposeTest {
    private val customConfig = ComposeUiTestConfig(
        failurePolicy = TestFailurePolicy(
            screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled,
            uiHierarchyCaptureMode = TestFailurePolicy.CaptureMode.Enabled
        )
    )

    @Test
    fun myFirstTest() = runComposeUiTest(config = customConfig) {
        // ...
    }
}

ใช้ตัวแฮนเดิลข้อผิดพลาดที่กำหนดเอง

หากต้องการกำหนดลักษณะการทำงานที่กำหนดเองสำหรับการทดสอบที่ไม่สำเร็จ ให้เพิ่ม TestFailureHandler ลงในfailureHandlers list ตัวแฮนเดิลแต่ละตัว จะได้รับออบเจ็กต์ FailureContext ที่มีข้อผิดพลาดเดิมและ รายการอาร์ติแฟกต์ที่สร้างขึ้นโดยตัวแฮนเดิลของไปป์ไลน์ก่อนหน้า

class MyComposeTestWithHandler {
    private val customConfig = ComposeUiTestConfig(
        failurePolicy = TestFailurePolicy(
            screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled,
            failureHandlers = listOf(
                TestFailureHandler { context ->
                    val screenshot = context.artifacts.firstOrNull {
                        it.type == FailureArtifact.Type.Screenshot
                    }
                    // ...
                }
            )
        )
    )

    @get:Rule
    val rule = createComposeRule(config = customConfig)

    // ...
}

กำหนดค่าการจับภาพสำหรับชุดโปรแกรมทดสอบทั้งหมด

คุณเปิดใช้การจับภาพอาร์ติแฟกต์ที่ล้มเหลวสำหรับชุดโปรแกรมทดสอบทั้งหมดได้โดยส่งอาร์กิวเมนต์ของเครื่องมือเรียกใช้การวัดคุมในไฟล์ build.gradle ของโมดูล ซึ่งจะ ช่วยให้ไม่ต้องอัปเดตไฟล์ทดสอบแต่ละไฟล์

// build.gradle.kts
android {
    defaultConfig {
        // ...
        testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isUiHierarchyCaptureEnabled"] = "true"
        testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isScreenshotCaptureEnabled"] = "true"
    }
}

ลำดับความสำคัญของการกำหนดค่า

เฟรมเวิร์กจะประเมินทั้งอาร์กิวเมนต์ของเครื่องมือทดสอบในเครื่อง TestFailurePolicyและระดับชุดทดสอบ

  • หากคุณตั้งค่าโหมดเป็น CaptureMode.Enabled/Disabled อย่างชัดเจนในfailurePolicyการทดสอบ ระบบจะลบล้างอาร์กิวเมนต์ของโปรแกรมเรียกใช้
  • หากตั้งค่าโหมดเป็น CaptureMode.Unspecified (หรือปล่อยให้ failurePolicy เป็น null) เฟรมเวิร์กจะกลับไปใช้อาร์กิวเมนต์ของ Runner

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

  • ทดสอบแอปใน Android: หน้า Landing Page หลักของการทดสอบ Android จะให้มุมมองที่กว้างขึ้นเกี่ยวกับพื้นฐานและเทคนิคการทดสอบ
  • พื้นฐานของการทดสอบ: ดูข้อมูลเพิ่มเติม เกี่ยวกับแนวคิดหลักที่อยู่เบื้องหลังการทดสอบแอป Android
  • การทดสอบในเครื่อง: คุณสามารถทำการทดสอบบางอย่างในเครื่องบนเวิร์กสเตชันของคุณเองได้
  • การทดสอบที่มีการวัดคุม: คุณควรเรียกใช้การทดสอบที่มีการวัดคุมด้วย กล่าวคือ การทดสอบที่ทำงานโดยตรงในอุปกรณ์
  • การรวมอย่างต่อเนื่อง: การรวมอย่างต่อเนื่องช่วยให้คุณผสานรวมการทดสอบเข้ากับไปป์ไลน์การทำให้ใช้งานได้
  • ทดสอบขนาดหน้าจอต่างๆ: เนื่องจากผู้ใช้มีอุปกรณ์ให้เลือกมากมาย คุณจึงควรทดสอบขนาดหน้าจอต่างๆ
  • Espresso: แม้ว่าจะมีไว้สำหรับ UI ที่อิงตาม View แต่ความรู้เกี่ยวกับ Espresso ก็ยังเป็นประโยชน์สำหรับบางแง่มุมของการทดสอบ Compose