Health Connect Test kitaplığını kullanarak birim testleri oluşturma

Health Connect Testing kitaplığı (androidx.health.connect:connect-testing), otomatik testlerin oluşturulmasını kolaylaştırır. Bu kitaplığı, uygulamanızın davranışını doğrulamak ve manuel olarak test edilmesi zor olan nadir durumlara doğru şekilde yanıt verdiğini onaylamak için kullanabilirsiniz.

Kitaplığı kullanarak yerel birim testleri oluşturabilirsiniz. Bu testler genellikle uygulamanızdaki Health Connect istemcisiyle etkileşimde bulunan sınıfların davranışını doğrular.

Kitaplığı kullanmaya başlamak için test bağımlılığı olarak ekleyin:

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

Kitaplığa giriş noktası, testlerde HealthConnectClient yerine kullandığınız FakeHealthConnectClient sınıfıdır. FakeHealthConnectClient aşağıdaki özelliklere sahiptir:

  • Kayıtların bellekteki temsili. Bu sayede kayıtları ekleyebilir, kaldırabilir, silebilir ve okuyabilirsiniz.
  • Değişiklik jetonları oluşturma ve değişiklik izleme
  • Kayıtlar ve değişiklikler için sayfalara ayırma
  • Toplama yanıtları, taslaklarla desteklenir.
  • Herhangi bir işlevin istisna oluşturmasına izin verir.
  • İzin kontrollerini taklit etmek için kullanılabilecek bir FakePermissionController

Testlerde bağımlılıkları değiştirme hakkında daha fazla bilgi edinmek için Android'de Bağımlılık Ekleme başlıklı makaleyi inceleyin. Sahteler hakkında daha fazla bilgi edinmek için Android'de test çiftlerini kullanma başlıklı makaleyi okuyun.

Örneğin, istemciyle etkileşimde bulunan sınıfın adı HealthConnectManager ise ve bağımlılık olarak HealthConnectClient alıyorsa şöyle görünür:

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

Testlerde, test edilen sınıfınıza bunun yerine sahte bir değer iletebilirsiniz:

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

Bu test, fetchReport işlevinin HealthConnectManager içinde kayıtları etkinliğe göre düzgün şekilde filtrelediğini doğrular.

İstisnaları doğrulama

HealthConnectClient numarasına yapılan aramaların neredeyse tamamında istisna oluşabilir. Örneğin, insertRecords ile ilgili dokümanlarda şu istisnalar belirtilir:

  • IPC ile ilgili tüm taşıma hataları için @throws android.os.RemoteException
  • @throws SecurityException izinsiz erişim istekleri için.
  • @throws java.io.IOException için tüm disk G/Ç sorunları.

Bu istisnalar, bağlantının kötü olması veya cihazda yer kalmaması gibi durumları kapsar. Uygulamanız, bu çalışma zamanı sorunlarına her an ortaya çıkabilecekleri için doğru şekilde tepki vermelidir.

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

Toplama

Toplama çağrıları sahte uygulamalara sahip değildir. Bunun yerine, toplama çağrıları, belirli bir şekilde davranacak şekilde programlayabileceğiniz sapları kullanır. Saplamalara overrides özelliğinin FakeHealthConnectClient üzerinden erişebilirsiniz.

Örneğin, toplama işlevini belirli bir sonucu döndürecek şekilde programlayabilirsiniz:

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)

Ardından, bu örnekte HealthConnectManager olan test edilen sınıfınızın sonucu doğru şekilde işlediğini doğrulayabilirsiniz:

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

İzinler

Test kitaplığı, FakePermissionController içerir. Bu kitaplık, FakeHealthConnectClient için bağımlılık olarak iletilebilir.

Test edilen öğeniz, izinleri kontrol etmek için PermissionController HealthConnectClient arayüzünün permissionController özelliği üzerinden erişilen permissionController öğesini kullanabilir. Bu işlem genellikle istemciye yapılan her çağrıdan önce gerçekleştirilir.

Bu işlevi test etmek için FakePermissionController kullanarak hangi izinlerin kullanılabilir olduğunu ayarlayabilirsiniz:

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

Sayfaları numaralandırma

Sayfalara ayırma, çok yaygın bir hata kaynağıdır. Bu nedenle FakeHealthConnectClient, kayıtlar ve değişiklikler için sayfalara ayırma uygulamanızın doğru şekilde çalıştığını doğrulamanıza yardımcı olacak mekanizmalar sunar.

Test edilen öğeniz (örneğimizde HealthConnectManager), ReadRecordsRequest içinde sayfa boyutunu belirtebilir:

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

Sayfa boyutunu 2 gibi küçük bir değere ayarlayarak sayfalara ayırma özelliğini test edebilirsiniz. Örneğin, readRecords 3 farklı sayfa döndürecek şekilde 5 kayıt ekleyebilirsiniz:

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

Test verileri

Kitaplıkta henüz sahte veri oluşturmaya yönelik API'ler bulunmamaktadır ancak kitaplık tarafından kullanılan verileri ve oluşturucuları Android Code Search'te kullanabilirsiniz.

Testlerde meta veri değerlerini taklit etmek için MetadataTestHelper kullanabilirsiniz. Bu, kayıt ekleme sırasında Health Connect'in meta veri değerlerini doldurmasını simüle eden populatedWithTestValues() uzantı işlevini sağlar.

Kütükler

FakeHealthConnectClient öğesinin overrides özelliği, işlevlerinden herhangi birini çağrıldığında istisna oluşturacak şekilde programlamanıza (veya stub out) olanak tanır. Toplama çağrıları rastgele veriler de döndürebilir ve birden fazla yanıtın sıraya alınmasını destekler. Daha fazla bilgi için Stub ve MutableStub sayfalarını inceleyin.

Sıra dışı durumların özeti

  • İstemci istisna oluşturduğunda uygulamanızın beklendiği gibi davrandığını doğrulayın. Hangi istisnaları kontrol etmeniz gerektiğini öğrenmek için her işlevin dokümanlarını inceleyin.
  • İstemciye yaptığınız her çağrıdan önce uygun izin kontrolünün yapıldığını doğrulayın.
  • Sayfalara ayırma uygulamanızı doğrulayın.
  • Birden fazla sayfa getirildiğinde ancak birinin jetonunun süresi dolduğunda ne olduğunu doğrulayın.