Biblioteca de testes do app Conexão Saúde (androidx.health.connect:connect-testing
)
simplifica a criação de testes automatizados. Você pode usar esta biblioteca para verificar
o comportamento do aplicativo e confirmar se ele responde corretamente
casos incomuns, difíceis de testar manualmente.
Você pode usar a biblioteca para criar testes de unidade locais, que geralmente verificam o comportamento das classes no app que interagem com a Conexão Saúde cliente.
Para começar a usar a biblioteca, adicione-a como uma dependência de teste:
testImplementation("androidx.health.connect:connect-testing:1.0.0-alpha01")
O ponto de entrada para a biblioteca é a classe FakeHealthConnectClient
, que você
usado em testes para substituir HealthConnectClient
. O FakeHealthConnectClient
tem os seguintes recursos:
- Uma representação de registros na memória, para que você possa inserir, remover, excluir e ler
- Geração de tokens de mudança e acompanhamento de mudanças
- Paginação de registros e alterações
- As respostas de agregação são compatíveis com stubs
- Permite que qualquer função gere exceções
- Um
FakePermissionController
que pode ser usado para emular verificações de permissões.
Para saber mais sobre como substituir dependências em testes, leia Injeção de dependências no Android. Para saber mais sobre conteúdo falso, leia Como usar testes duplos no Android.
Por exemplo, se a classe que interage com o cliente for chamada
HealthConnectManager
e usa um HealthConnectClient
como dependência,
ficaria assim:
class HealthConnectManager(
private val healthConnectClient: HealthConnectClient,
...
) { }
Em testes, você pode transmitir um falso para a classe em teste:
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)
}
}
Este teste verifica se a função fetchReport
fictícia na
O HealthConnectManager
filtra corretamente os registros por atividade.
Como verificar exceções
Quase todas as chamadas para HealthConnectClient
podem gerar exceções. Por exemplo:
a documentação de insertRecords
menciona estas exceções:
@throws android.os.RemoteException
para qualquer falha de transporte da IPC.@throws SecurityException
para solicitações com acesso não permitido.@throws java.io.IOException
para qualquer problema de E/S de disco.
Essas exceções abrangem casos como uma conexão ruim ou falta de espaço no dispositivo. Seu app precisa reagir corretamente a esses problemas de execução, já que eles podem acontecer a qualquer 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)
}
Agregação
As chamadas de agregação não têm implementações falsas. Em vez disso, as chamadas de agregação
usar stubs que podem ser programados para se comportar de uma determinada maneira. Acesse o
usando a propriedade overrides
do FakeHealthConnectClient
.
Por exemplo, é possível programar a função agregada para retornar um resultado específico:
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)
Em seguida, verifique se a classe está em teste (HealthConnectManager
) neste
caso, processou o resultado corretamente:
// 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)
Permissões
A biblioteca de testes inclui um FakePermissionController
, que pode ser transmitido
como uma dependência de FakeHealthConnectClient
.
O objeto em testes pode usar o PermissionController—through
propriedade permissionController
da interface HealthConnectClient
. Para verificar,
para saber as permissões. Isso normalmente é feito antes de cada chamada para o cliente.
Para testar essa funcionalidade, você pode definir quais permissões estão disponíveis usando
o 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)
}
Paginação
A paginação é uma fonte muito comum de bugs, então FakeHealthConnectClient
fornece mecanismos para ajudar a verificar se a implementação de paginação para
registros e alterações se comporta corretamente.
O objeto em teste, HealthConnectManager
em nosso exemplo, pode especificar a
tamanho da página no ReadRecordsRequest
:
fun fetchRecordsReport(pageSize: Int = 1000) }
val pagedRequest =
ReadRecordsRequest(
timeRangeFilter = ...,
recordType = ...,
pageToken = page1.pageToken,
pageSize = pageSize,
)
val page = client.readRecords(pagedRequest)
...
Definir o tamanho da página com um valor pequeno, como 2, permite testar facilmente
paginação. Por exemplo, é possível inserir cinco registros para que readRecords
retorne 3.
páginas diferentes:
@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)
}
Dados de teste
A biblioteca ainda não inclui APIs para gerar dados falsos, mas você pode usar o dados e geradores usados pela biblioteca na Pesquisa de código do Android.
Stubs
A propriedade overrides
de FakeHealthConnectClient
permite programar (ou
criar stubs) de qualquer uma das funções para gerar exceções quando chamadas.
As chamadas de agregação também podem retornar dados arbitrários e oferece suporte ao enfileiramento
múltiplas respostas. Consulte Stub
e MutableStub
para mais informações.
Resumo dos casos extremos
- Verifique se o aplicativo se comporta conforme o esperado quando o cliente gera exceções. Verifique a documentação de cada função para descobrir quais exceções você o que deve ser verificado.
- Verifique se cada chamada feita para o cliente é precedida pelo verificação de permissões.
- Verifique sua implementação de paginação.
- Verifique o que acontece quando você busca várias páginas, mas uma delas tem o URL expirado com base no token correto anterior.