Membuat pengujian unit menggunakan library Pengujian Health Connect

Library Pengujian Health Connect (androidx.health.connect:connect-testing) menyederhanakan pembuatan pengujian otomatis. Anda dapat menggunakan {i>library<i} ini untuk memverifikasi perilaku aplikasi dan memvalidasi bahwa aplikasi merespons dengan benar kasus yang jarang terjadi, yang sulit diuji secara manual.

Anda dapat menggunakan library untuk membuat pengujian unit lokal, yang biasanya memverifikasi perilaku class di aplikasi Anda yang berinteraksi dengan Health Connect klien Anda.

Untuk mulai menggunakan library, tambahkan library sebagai dependensi pengujian:

 testImplementation("androidx.health.connect:connect-testing:1.0.0-alpha01")

Titik entri ke library adalah class FakeHealthConnectClient, yang dapat gunakan dalam pengujian untuk mengganti HealthConnectClient. FakeHealthConnectClient memiliki fitur berikut:

  • Representasi rekaman dalam memori, sehingga Anda dapat menyisipkan, menghapus, menghapus, dan bacain
  • Pembuatan token perubahan dan pelacakan perubahan
  • Penomoran halaman untuk catatan dan perubahan
  • Respons agregasi didukung dengan stub
  • Mengizinkan fungsi apa pun menampilkan pengecualian
  • FakePermissionController yang dapat digunakan untuk mengemulasi pemeriksaan izin

Untuk mempelajari lebih lanjut cara mengganti dependensi dalam pengujian, baca Injeksi Dependensi di Android. Untuk mengetahui informasi palsu lebih lanjut, baca Menggunakan dummy pengujian di Android.

Misalnya, jika class yang berinteraksi dengan klien dipanggil HealthConnectManager dan memerlukan HealthConnectClient sebagai dependensi, akan terlihat seperti ini:

class HealthConnectManager(
    private val healthConnectClient: HealthConnectClient,
    ...
) { }

Dalam pengujian, Anda dapat meneruskan kode palsu ke class yang sedang diuji:

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

Pengujian ini memverifikasi bahwa fungsi fetchReport fiktif dalam HealthConnectManager memfilter catatan berdasarkan aktivitas dengan benar.

Memverifikasi pengecualian

Hampir setiap panggilan ke HealthConnectClient dapat menampilkan pengecualian. Misalnya, dokumentasi untuk insertRecords menyebutkan pengecualian berikut:

  • @throws android.os.RemoteException untuk kegagalan transportasi IPC.
  • @throws SecurityException untuk permintaan dengan akses yang tidak diizinkan.
  • @throws java.io.IOException untuk masalah I/O disk.

Pengecualian ini mencakup kasus seperti koneksi yang buruk atau tidak ada ruang tersisa di perangkat seluler. Aplikasi Anda harus bereaksi dengan benar terhadap masalah runtime ini, karena hal itu dapat kapan saja.

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

Agregasi

Panggilan agregasi tidak memiliki implementasi palsu. Sebagai gantinya, panggilan agregasi menggunakan stub yang dapat Anda program untuk berperilaku dengan cara tertentu. Anda dapat mengakses stub melalui properti overrides dari FakeHealthConnectClient.

Misalnya, Anda dapat memprogram fungsi agregat untuk menampilkan hasil tertentu:

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)

Kemudian, Anda dapat memverifikasi bahwa kelas yang sedang diuji, HealthConnectManager dalam yang sesuai, memproses hasilnya dengan benar:

// 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)

Izin

Library pengujian menyertakan FakePermissionController, yang dapat diteruskan sebagai dependensi untuk FakeHealthConnectClient.

Subjek yang sedang diuji dapat menggunakan PermissionController—through Properti permissionController antarmuka HealthConnectClient—untuk memeriksa untuk izin akses. Hal ini biasanya dilakukan sebelum setiap panggilan ke klien.

Untuk menguji fungsi ini, Anda dapat mengatur izin mana yang tersedia menggunakan 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)
}

Penomoran halaman

Penomoran halaman adalah sumber bug yang sangat umum, jadi FakeHealthConnectClient menyediakan mekanisme untuk membantu Anda memverifikasi bahwa implementasi {i>paging <i}Anda untuk rekaman dan perubahan berfungsi dengan benar.

Subjek Anda yang sedang diuji, HealthConnectManager dalam contoh kami, dapat menentukan ukuran halaman di ReadRecordsRequest:

fun fetchRecordsReport(pageSize: Int = 1000) }
    val pagedRequest =
        ReadRecordsRequest(
            timeRangeFilter = ...,
            recordType = ...,
            pageToken = page1.pageToken,
            pageSize = pageSize,
        )
    val page = client.readRecords(pagedRequest)
    ...

Menyetel ukuran halaman ke nilai kecil, seperti 2, akan memudahkan Anda menguji penomoran halaman. Misalnya, Anda dapat menyisipkan 5 data sehingga readRecords menampilkan 3 halaman yang berbeda:

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

Uji data

Library ini belum menyertakan API untuk menghasilkan data palsu, tetapi Anda dapat menggunakan class data dan generator yang digunakan oleh library di Android Code Search.

Stub

Properti overrides dari FakeHealthConnectClient memungkinkan Anda memprogram (atau stub out) salah satu fungsinya sehingga akan menampilkan pengecualian saat dipanggil. Panggilan agregasi juga dapat menampilkan data arbitrer, serta mendukung pengantrean beberapa respons. Lihat Stub dan MutableStub untuk informasi selengkapnya.

Ringkasan kasus ekstrem

  • Verifikasi bahwa aplikasi Anda berperilaku seperti yang diharapkan saat klien menampilkan pengecualian. Periksa dokumentasi setiap fungsi untuk mengetahui pengecualian apa yang Anda harus diperiksa.
  • Verifikasi bahwa setiap panggilan yang Anda lakukan kepada klien didahului oleh pemeriksaan izin akses.
  • Verifikasi penerapan penomoran halaman.
  • Memverifikasi apa yang terjadi saat Anda mengambil beberapa halaman, tetapi satu halaman memiliki masa berlaku sebelumnya yang benar.