La libreria di test di Health Connect (androidx.health.connect:connect-testing
)
semplifica la creazione di test automatici. Puoi utilizzare questa libreria per verificare
il comportamento della tua applicazione e convalidare che risponda correttamente a
casi insoliti, difficili da testare manualmente.
Puoi utilizzare la libreria per creare test delle unità locali, che in genere verificano il comportamento delle classi nella tua app che interagiscono con il client Health Connect.
Per iniziare a utilizzare la libreria, aggiungila come dipendenza di test:
testImplementation("androidx.health.connect:connect-testing:1.0.0-alpha01")
Il punto di accesso alla libreria è la classe FakeHealthConnectClient
, che
utilizzi nei test per sostituire HealthConnectClient
. FakeHealthConnectClient
ha le seguenti funzionalità:
- Una rappresentazione in memoria dei record, in modo da poterli inserire, rimuovere, eliminare e leggere.
- Generazione di token di modifica e monitoraggio delle modifiche
- Impaginazione per record e modifiche
- Le risposte di aggregazione sono supportate con gli stub
- Consente a qualsiasi funzione di generare eccezioni
- Un
FakePermissionController
che può essere utilizzato per emulare i controlli delle autorizzazioni
Per scoprire di più sulla sostituzione delle dipendenze nei test, leggi Dependency Injection in Android. Per saperne di più sui test doppi, leggi Utilizzo di test doppi in Android.
Ad esempio, se la classe che interagisce con il client si chiama
HealthConnectManager
e accetta HealthConnectClient
come dipendenza, il codice
sarà simile a questo:
class HealthConnectManager(
private val healthConnectClient: HealthConnectClient,
...
) { }
Nei test, puoi passare un falso alla tua classe in fase di test:
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)
}
}
Questo test verifica che la funzione fittizia fetchReport
in
HealthConnectManager
filtri correttamente i record in base all'attività.
Verifica delle eccezioni
Quasi tutte le chiamate a HealthConnectClient
possono generare eccezioni. Ad esempio,
la documentazione per insertRecords
menziona queste eccezioni:
@throws android.os.RemoteException
per eventuali errori di trasporto IPC.@throws SecurityException
per le richieste con accesso non consentito.@throws java.io.IOException
per eventuali problemi di I/O del disco.
Queste eccezioni riguardano casi come una connessione instabile o spazio insufficiente sul dispositivo. La tua app deve reagire correttamente a questi problemi di runtime, in quanto possono verificarsi in qualsiasi momento.
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)
}
Aggregazione
Le chiamate di aggregazione non hanno implementazioni false. Invece, le chiamate di aggregazione
utilizzano stub che puoi programmare per comportarsi in un determinato modo. Puoi accedere agli
stub tramite la proprietà overrides
di FakeHealthConnectClient
.
Ad esempio, puoi programmare la funzione aggregata in modo che restituisca un risultato specifico:
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)
Dopodiché, puoi verificare che la classe in fase di test, HealthConnectManager
in questo caso, abbia elaborato correttamente il risultato:
// 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)
Autorizzazioni
La libreria di test include un FakePermissionController
, che può essere passato
come dipendenza a FakeHealthConnectClient
.
Il soggetto sottoposto a test può utilizzare la proprietà PermissionController—through
permissionController
dell'interfaccia HealthConnectClient
per verificare
le autorizzazioni. In genere, questa operazione viene eseguita prima di ogni chiamata al client.
Per testare questa funzionalità, puoi impostare le autorizzazioni disponibili utilizzando
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)
}
Impaginazione
La paginazione è una fonte molto comune di bug, pertanto FakeHealthConnectClient
fornisce meccanismi per aiutarti a verificare che l'implementazione della paginazione per
record e modifiche si comporti correttamente.
Il soggetto in esame, HealthConnectManager
nel nostro esempio, può specificare le
dimensioni della pagina in ReadRecordsRequest
:
fun fetchRecordsReport(pageSize: Int = 1000) }
val pagedRequest =
ReadRecordsRequest(
timeRangeFilter = ...,
recordType = ...,
pageToken = page1.pageToken,
pageSize = pageSize,
)
val page = client.readRecords(pagedRequest)
...
Se imposti le dimensioni della pagina su un valore ridotto, ad esempio 2, puoi testare
la paginazione. Ad esempio, puoi inserire 5 record in modo che readRecords
restituisca
3 pagine diverse:
@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)
}
Dati di test
La libreria non include ancora API per generare dati falsi, ma puoi utilizzare i dati e i generatori utilizzati dalla libreria nella ricerca di codice Android.
Per simulare i valori dei metadati nei test, puoi utilizzare
MetadataTestHelper
. In questo modo viene fornita la funzione di estensione populatedWithTestValues()
, che simula il popolamento dei valori dei metadati da parte di Connessione Salute durante l'inserimento dei record.
Stubs
La proprietà overrides
di FakeHealthConnectClient
consente di programmare (o
stub out) una qualsiasi delle sue funzioni in modo che generino eccezioni quando vengono chiamate.
Le chiamate di aggregazione possono anche restituire dati arbitrari e supportano l'accodamento
di più risposte. Per saperne di più, consulta Stub
e MutableStub
.
Riepilogo dei casi limite
- Verifica che la tua app si comporti come previsto quando il client genera eccezioni. Consulta la documentazione di ogni funzione per capire quali eccezioni devi controllare.
- Verifica che ogni chiamata al client sia preceduta dal controllo delle autorizzazioni corrette.
- Verifica l'implementazione della paginazione.
- Verifica cosa succede quando recuperi più pagine, ma una ha un token scaduto.