Biblioteka testów Health Connect (androidx.health.connect:connect-testing
)
upraszcza tworzenie testów zautomatyzowanych. Za pomocą tej biblioteki możesz zweryfikować
działania aplikacji i sprawdzanie, czy odpowiada ona prawidłowo
nietypowe przypadki, które trudno jest przetestować ręcznie.
Możesz jej używać do tworzenia lokalnych testów jednostkowych, które zwykle sprawdzają zachowanie zajęć w aplikacji, które współdziałają z Health Connect; .
Aby zacząć korzystać z biblioteki, dodaj ją jako zależność testową:
testImplementation("androidx.health.connect:connect-testing:1.0.0-alpha01")
Punktem wejścia do biblioteki jest klasa FakeHealthConnectClient
, której
użyć w testach, aby zastąpić HealthConnectClient
. FakeHealthConnectClient
ma te funkcje:
- Reprezentacja rekordów w pamięci, dzięki czemu można wstawiać, usuwać, usuwać przeczytaj je
- Generowanie tokenów zmian i ich śledzenie
- Podział rekordów i zmian na strony
- Odpowiedzi agregacji są obsługiwane z krotkami
- Zezwala dowolnej funkcji na zgłaszanie wyjątków
- Interfejs
FakePermissionController
, który może być używany do emulacji sprawdzania uprawnień
Więcej informacji o zastępowaniu zależności w testach znajdziesz w artykule Wstrzykiwanie zależności w Androidzie Aby dowiedzieć się więcej o podróbkach, przeczytaj artykuł Korzystanie z podwójnych testów na Androidzie
Jeśli na przykład klasa wchodząca w interakcję z klientem jest wywoływana
HealthConnectManager
i wymaga HealthConnectClient
jako zależność,
będzie wyglądać tak:
class HealthConnectManager(
private val healthConnectClient: HealthConnectClient,
...
) { }
W ramach testów możesz zamiast tego przekazać fałszywe treści klasie, które są testowane:
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)
}
}
W ramach tego testu sprawdzamy, czy fikcyjna funkcja fetchReport
w
HealthConnectManager
prawidłowo filtruje rekordy według aktywności.
Weryfikuję wyjątki
Prawie każde wywołanie funkcji HealthConnectClient
może zgłosić wyjątki. Przykład:
w dokumentacji dotyczącej domeny insertRecords
wymieniono te wyjątki:
@throws android.os.RemoteException
w przypadku awarii transportu IPC.@throws SecurityException
w przypadku żądań z niedozwolonym dostępem.@throws java.io.IOException
w przypadku problemów z I/O dysku.
Te wyjątki dotyczą np. słabego połączenia lub braku miejsca na stronie urządzenia. Twoja aplikacja musi prawidłowo reagować na te problemy w czasie działania aplikacji, mogą wystąpić w każdej chwili.
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)
}
Agregacja
Wywołania agregujące nie zawierają fałszywych implementacji. Zamiast tego wywołania agregacji
z wycinkami, które możesz zaprogramować tak, aby działały w określony sposób. Aby uzyskać dostęp do
za pomocą właściwości overrides
elementu FakeHealthConnectClient
.
Na przykład funkcję agregacji można zaprogramować w taki sposób, aby zwracała określony wynik:
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)
Następnie możesz sprawdzić, czy testowane zajęcia, HealthConnectManager
, na
udało się przetworzyć wynik prawidłowo:
// 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)
Uprawnienia
Biblioteka testowa zawiera zasób FakePermissionController
, który można przekazać
jako zależność do FakeHealthConnectClient
.
Testowany obiekt może korzystać z: PermissionController—through
właściwość permissionController
interfejsu HealthConnectClient
– do sprawdzenia
uprawnień. Zwykle robi się to przed każdym połączeniem z klientem.
Aby przetestować tę funkcję, możesz określić, jakie uprawnienia mają być dostępne w
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)
}
Podział na strony
Podział na strony jest bardzo częstym źródłem błędów, więc FakeHealthConnectClient
udostępnia mechanizmy, które pomagają sprawdzić, czy implementacja stronicowania
a rekordy i zmiany działają prawidłowo.
Sprawdzany obiekt (HealthConnectManager
w naszym przykładzie) może określić
rozmiar strony w ReadRecordsRequest
:
fun fetchRecordsReport(pageSize: Int = 1000) }
val pagedRequest =
ReadRecordsRequest(
timeRangeFilter = ...,
recordType = ...,
pageToken = page1.pageToken,
pageSize = pageSize,
)
val page = client.readRecords(pagedRequest)
...
Ustawienie małej wartości (np. 2) na stronie umożliwia łatwe testowanie
podział na strony. Możesz na przykład wstawić 5 rekordów, tak aby funkcja readRecords
zwracała 3 rekordy
różne strony:
@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)
}
Dane testowe
Biblioteka nie zawiera jeszcze interfejsów API do generowania fałszywych danych, ale możesz użyć dane i generatory używane przez bibliotekę w wyszukiwarce kodu na Androidzie.
Fragmenty
Właściwość overrides
elementu FakeHealthConnectClient
umożliwia programowanie (lub
wytnij) dowolną z jej funkcji, tak aby po wywołaniu były zgłaszane wyjątki.
Wywołania agregacji również mogą zwracać dowolne dane i obsługują kolejkowanie
wiele odpowiedzi. Więcej informacji znajdziesz w sekcjach Stub
i MutableStub
.
Podsumowanie przypadków skrajnych
- Sprawdź, czy aplikacja działa zgodnie z oczekiwaniami, gdy klient zgłasza wyjątki. Zapoznaj się z dokumentacją poszczególnych funkcji, aby dowiedzieć się, jakich wyjątków powinien sprawdzić.
- Sprawdź, czy każde połączenie z klientem jest poprzedzone odpowiednim sprawdzić uprawnienia.
- Sprawdź implementację podziału na strony.
- Sprawdź, co się dzieje w przypadku pobrania wielu stron, ale jedna z nich straciła ważność token.