ヘルスコネクト テスト ライブラリ(androidx.health.connect:connect-testing
)
自動テストの作成を簡素化できます。このライブラリを使用して、
適切に応答することを検証し、
手動でのテストは困難です。
このライブラリを使用して、ローカル単体テストを作成できます。通常、このテストは、 ヘルスコネクトとやり取りするアプリ内のクラスの動作 できます。
ライブラリの使用を開始するには、テストの依存関係として追加します。
testImplementation("androidx.health.connect:connect-testing:1.0.0-alpha01")
ライブラリのエントリ ポイントは FakeHealthConnectClient
クラスです。このクラスは、
テストで使用する HealthConnectClient
の置き換え。FakeHealthConnectClient
次の機能があります。
- レコードのインメモリ表現。挿入、削除、削除、 読む
- 変更トークンの生成と変更の追跡
- レコードと変更のページ分け
- 集計レスポンスはスタブでサポートされています
- 任意の関数が例外をスローできるようにする
- 権限チェックのエミュレートに使用できる
FakePermissionController
テストの依存関係を置き換える方法について詳しくは、以下をご覧ください。 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
のドキュメントには、次の例外が記載されています。
- IPC 転送障害の場合は
@throws android.os.RemoteException
。 - アクセスが許可されていないリクエストの場合は
@throws SecurityException
。 - ディスク I/O の問題の場合は
@throws java.io.IOException
。
この例外は、接続が不安定であったり、スペースが残っていない場合や、 できます。アプリは、こうしたランタイムの問題に正しく対応する必要があります。 発生します。
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)
}
集計
集約呼び出しに偽の実装はありません。代わりに、集計関数を使用して
スタブを使用して、特定の動作をするようにプログラムできます。こちらの
スタブに FakeHealthConnectClient
の overrides
プロパティを使用。
たとえば、特定の結果を返すように集計関数をプログラムできます。
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
が含まれており、これは
FakeHealthConnectClient
への依存関係として指定します。
テスト対象は、PermissionController—through
HealthConnectClient
インターフェースの permissionController
プロパティ。
ご確認ください。これは通常、クライアントへのすべての呼び出しの前に行われます。
この機能をテストするには、
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
には、ページングの実装が Google Cloud 内で
正しく機能することを確認します。
テスト対象(この例では HealthConnectManager
)は、
ReadRecordsRequest
のページサイズ:
fun fetchRecordsReport(pageSize: Int = 1000) }
val pagedRequest =
ReadRecordsRequest(
timeRangeFilter = ...,
recordType = ...,
pageToken = page1.pageToken,
pageSize = pageSize,
)
val page = client.readRecords(pagedRequest)
...
ページサイズを小さな値(2 など)に設定すると、
ページ分け。たとえば、readRecords
が 3 を返すように 5 つのレコードを挿入できます。
ページごとに異なります:
@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 ソースコード検索のライブラリで使用されるデータとジェネレータ。
スタブ
FakeHealthConnectClient
の overrides
プロパティを使用すると、
スタブアウト)を使用して、例外をスローするようにします。
集計呼び出しでは任意のデータを返すこともでき、
複数回答が返されます詳細については、Stub
と MutableStub
をご覧ください。
エッジケースの概要
- クライアントが例外をスローしたときに、アプリが期待どおりに動作することを確認します。 各関数のドキュメントを参照して、どの例外が例外として使用されるかについては、 確認します。
- クライアントに対して行うすべての呼び出しの前に、必ず適切な 許可チェックを行います。
- ページ分けの実装を確認します。
- 複数のページを取得したときに 1 つの有効期限が切れている場合 あります。