ไลบรารีการทดสอบ Health Connect (androidx.health.connect:connect-testing)
ช่วยให้การสร้างการทดสอบอัตโนมัติเป็นเรื่องง่าย คุณสามารถใช้ไลบรารีนี้เพื่อยืนยัน
ลักษณะการทำงานของแอปพลิเคชันและตรวจสอบว่าแอปพลิเคชันตอบสนองอย่างถูกต้องใน
กรณีที่พบได้ยาก ซึ่งทดสอบด้วยตนเองได้ยาก
คุณสามารถใช้ไลบรารีเพื่อสร้างการทดสอบหน่วยในเครื่อง ซึ่งโดยปกติจะตรวจสอบลักษณะการทำงานของคลาสในแอปที่โต้ตอบกับไคลเอ็นต์ Health Connect
หากต้องการเริ่มใช้ไลบรารี ให้เพิ่มไลบรารีเป็นทรัพยากร Dependency สำหรับการทดสอบ
 testImplementation("androidx.health.connect:connect-testing:1.0.0-alpha01")
จุดแรกเข้าของไลบรารีคือคลาส FakeHealthConnectClient ซึ่งคุณใช้ในการทดสอบเพื่อแทนที่ HealthConnectClient FakeHealthConnectClient
มีฟีเจอร์ต่อไปนี้
- การแสดงระเบียนในหน่วยความจำเพื่อให้คุณแทรก นำออก ลบ และ อ่านระเบียนได้
- การสร้างโทเค็นการเปลี่ยนแปลงและการติดตามการเปลี่ยนแปลง
- การแบ่งหน้าสำหรับบันทึกและการเปลี่ยนแปลง
- ระบบรองรับการตอบกลับการรวบรวมข้อมูลด้วย Stub
- อนุญาตให้ฟังก์ชันใดก็ได้ส่งข้อยกเว้น
- FakePermissionControllerที่ใช้จำลองการตรวจสอบสิทธิ์ได้
ดูข้อมูลเพิ่มเติมเกี่ยวกับการแทนที่ทรัพยากร Dependency ในการทดสอบได้ที่การแทรกทรัพยากร Dependency ใน Android ดูข้อมูลเพิ่มเติมเกี่ยวกับออบเจ็กต์จำลองได้ที่การใช้ออบเจ็กต์ทดสอบแทนใน Android
เช่น หากคลาสที่โต้ตอบกับไคลเอ็นต์ชื่อ HealthConnectManager และใช้ HealthConnectClient เป็นการอ้างอิง จะมีลักษณะดังนี้
class HealthConnectManager(
    private val healthConnectClient: HealthConnectClient,
    ...
) { }
ในการทดสอบ คุณสามารถส่งออบเจ็กต์จำลองไปยังคลาสที่อยู่ภายใต้การทดสอบแทนได้
import androidx.health.connect.client.testing.ExperimentalTestingApi
import androidx.health.connect.client.testing.FakeHealthConnectClient
import kotlinx.coroutines.test.runTest
@OptIn(ExperimentalTestingApi::class)
class HealthConnectManagerTest {
    @Test
    fun readRecords_filterByActivity() = runTest {
        // Create a Fake with 2 running records.
        val fake = FakeHealthConnectClient()
        fake.insertRecords(listOf(fakeRunRecord1, fakeBikeRecord1))
        // Create a manager that depends on the fake.
        val manager = HealthConnectManager(fake)
        // Read running records only.
        val runningRecords = manager.fetchReport(activity = Running)
        // Verify that the records were filtered correctly.
        assertTrue(runningRecords.size == 1)
    }
}
การทดสอบนี้จะยืนยันว่าฟังก์ชัน fetchReport สมมติใน
HealthConnectManager กรองระเบียนตามกิจกรรมได้อย่างถูกต้อง
การยืนยันข้อยกเว้น
การเรียกใช้ HealthConnectClient เกือบทุกครั้งอาจทำให้เกิดข้อยกเว้น เช่น
เอกสารประกอบสำหรับ insertRecords ระบุข้อยกเว้นต่อไปนี้
- @throws android.os.RemoteExceptionสำหรับความล้มเหลวในการขนส่ง IPC
- @throws SecurityExceptionสำหรับคำขอที่มีสิทธิ์เข้าถึงที่ไม่ได้รับอนุญาต
- @throws java.io.IOExceptionสำหรับปัญหา I/O ของดิสก์
ข้อยกเว้นเหล่านี้ครอบคลุมกรณีต่างๆ เช่น การเชื่อมต่อไม่ดีหรือพื้นที่ใน อุปกรณ์ไม่เพียงพอ แอปของคุณต้องตอบสนองต่อปัญหาขณะรันไทม์เหล่านี้อย่างถูกต้อง เนื่องจากปัญหาอาจเกิดขึ้นได้ทุกเมื่อ
import androidx.health.connect.client.testing.stubs.stub
@Test
fun addRecords_throwsRemoteException_errorIsExposed() {
    // Create Fake that throws a RemoteException
    // when insertRecords is called.
    val fake = FakeHealthConnectClient()
    fake.overrides.insertRecords = stub { throw RemoteException() }
    // Create a manager that depends on the fake.
    val manager = HealthConnectManager(fake)
    // Insert a record.
    manager.addRecords(fakeRunRecord1)
    // Verify that the manager is exposing an error.
    assertTrue(manager.errors.size == 1)
}
การรวม
การเรียกการรวมจะไม่ใช้การติดตั้งใช้งานปลอม แต่การเรียกการรวบรวม
จะใช้ Stub ที่คุณตั้งโปรแกรมให้ทำงานในลักษณะหนึ่งๆ ได้ คุณเข้าถึง
สตับได้ผ่านพร็อพเพอร์ตี้ overrides ของ FakeHealthConnectClient
เช่น คุณสามารถตั้งโปรแกรมฟังก์ชันการรวมให้แสดงผลลัพธ์ที่เฉพาะเจาะจงได้ดังนี้
import androidx.health.connect.client.testing.AggregationResult
import androidx.health.connect.client.records.HeartRateRecord
import androidx.health.connect.client.records.ExerciseSessionRecord
import java.time.Duration
@Test
fun aggregate() {
    // Create a fake result.
    val result =
        AggregationResult(metrics =
            buildMap {
                put(HeartRateRecord.BPM_AVG, 74.0)
                put(
                    ExerciseSessionRecord.EXERCISE_DURATION_TOTAL,
                    Duration.ofMinutes(30)
                )
            }
        )
    // Create a fake that always returns the fake
    // result when aggregate() is called.
    val fake = FakeHealthConnectClient()
    fake.overrides.aggregate = stub(result)
จากนั้นคุณสามารถยืนยันว่าชั้นเรียนที่อยู่ระหว่างการทดสอบ HealthConnectManager ในกรณีนี้
ประมวลผลผลลัพธ์อย่างถูกต้องโดยทำดังนี้
// Create a manager that depends on the fake.
val manager = HealthConnectManager(fake)
// Call the function that in turn calls aggregate on the client.
val report = manager.getHeartRateReport()
// Verify that the manager is exposing an error.
assertThat(report.bpmAverage).isEqualTo(74.0)
สิทธิ์
ไลบรารีการทดสอบมี FakePermissionController ซึ่งส่งเป็นทรัพยากร Dependency ไปยัง FakeHealthConnectClient ได้
ผู้ที่อยู่ภายใต้การทดสอบสามารถใช้พร็อพเพอร์ตี้ PermissionController—throughpermissionController ของอินเทอร์เฟซ HealthConnectClient เพื่อตรวจสอบสิทธิ์ได้ โดยปกติจะดำเนินการก่อนการเรียกใช้ไคลเอ็นต์ทุกครั้ง
หากต้องการทดสอบฟังก์ชันนี้ คุณสามารถตั้งค่าสิทธิ์ที่พร้อมใช้งานได้โดยใช้FakePermissionController ดังนี้
import androidx.health.connect.client.testing.FakePermissionController
@Test
fun newRecords_noPermissions_errorIsExposed() {
    // Create a permission controller with no permissions.
    val permissionController = FakePermissionController(grantAll = false)
    // Create a fake client with the permission controller.
    val fake = FakeHealthConnectClient(permissionController = permissionController)
    // Create a manager that depends on the fake.
    val manager = HealthConnectManager(fake)
    // Call addRecords so that the permission check is made.
    manager.addRecords(fakeRunRecord1)
    // Verify that the manager is exposing an error.
    assertThat(manager.errors).hasSize(1)
}
การใส่เลขหน้า
การแบ่งหน้าเป็นแหล่งที่มาของข้อบกพร่องที่พบบ่อยมาก ดังนั้น FakeHealthConnectClient
จึงมีกลไกที่จะช่วยคุณยืนยันว่าการติดตั้งใช้งานการแบ่งหน้าสำหรับ
บันทึกและการเปลี่ยนแปลงทํางานอย่างถูกต้อง
HealthConnectManager ในตัวอย่างของเราสามารถระบุขนาดหน้าเว็บใน ReadRecordsRequest ได้ดังนี้
fun fetchRecordsReport(pageSize: Int = 1000) }
    val pagedRequest =
        ReadRecordsRequest(
            timeRangeFilter = ...,
            recordType = ...,
            pageToken = page1.pageToken,
            pageSize = pageSize,
        )
    val page = client.readRecords(pagedRequest)
    ...
การตั้งค่าขนาดหน้าเป็นค่าเล็กๆ เช่น 2 จะช่วยให้คุณทดสอบ
การแบ่งหน้าได้ เช่น คุณสามารถแทรก 5 ระเบียนเพื่อให้ readRecords แสดงผล 3 หน้าที่แตกต่างกัน ดังนี้
@Test
fun readRecords_multiplePages() = runTest {
    // Create a Fake with 2 running records.
    val fake = FakeHealthConnectClient()
    fake.insertRecords(generateRunningRecords(5))
    // Create a manager that depends on the fake.
    val manager = HealthConnectManager(fake)
    // Read records with a page size of 2.
    val report = manager.generateReport(pageSize = 2)
    // Verify that all the pages were processed correctly.
    assertTrue(report.records.size == 5)
}
ข้อมูลการทดสอบ
ไลบรารียังไม่มี API สำหรับสร้างข้อมูลปลอม แต่คุณสามารถใช้ข้อมูลและเครื่องมือสร้างที่ไลบรารีใช้ใน Android Code Search ได้
หากต้องการจำลองค่าข้อมูลเมตาในการทดสอบ คุณสามารถใช้
MetadataTestHelper ซึ่งจะให้populatedWithTestValues()ฟังก์ชันส่วนขยายที่จำลอง Health Connect
การป้อนค่าข้อมูลเมตาระหว่างการแทรกบันทึก
ตั๋ว
พร็อพเพอร์ตี้ overrides ของ FakeHealthConnectClient ช่วยให้คุณตั้งโปรแกรม (หรือจำลอง) ฟังก์ชันใดก็ได้เพื่อให้ฟังก์ชันเหล่านั้นแสดงข้อยกเว้นเมื่อมีการเรียกใช้
การเรียกใช้การรวบรวมยังแสดงผลข้อมูลที่กำหนดเองได้ และรองรับการจัดคิว
การตอบกลับหลายรายการ ดูข้อมูลเพิ่มเติมได้ที่ Stub และ MutableStub
สรุปกรณีสุดโต่ง
- ตรวจสอบว่าแอปทำงานตามที่คาดไว้เมื่อไคลเอ็นต์ส่งข้อยกเว้น ดูเอกสารประกอบของแต่ละฟังก์ชันเพื่อดูข้อยกเว้นที่คุณควรตรวจสอบ
- ตรวจสอบว่าการเรียกใช้ไคลเอ็นต์ทุกครั้งจะมีการตรวจสอบสิทธิ์ที่เหมาะสมก่อน
- ยืนยันการติดตั้งใช้งานการแบ่งหน้า
- ตรวจสอบสิ่งที่จะเกิดขึ้นเมื่อคุณดึงข้อมูลหลายหน้า แต่มีหน้าหนึ่งที่มีโทเค็นหมดอายุ
