Thư viện kiểm thử Health Connect (androidx.health.connect:connect-testing
) giúp đơn giản hoá việc tạo các bài kiểm thử tự động. Bạn có thể sử dụng thư viện này để xác minh hành vi của ứng dụng và xác thực rằng ứng dụng phản hồi đúng cách đối với các trường hợp không phổ biến (khó kiểm thử theo cách thủ công).
Bạn có thể dùng thư viện này để tạo các kiểm thử đơn vị cục bộ. Các kiểm thử này thường xác minh hành vi của các lớp trong ứng dụng tương tác với máy khách Health Connect.
Để bắt đầu sử dụng thư viện này, hãy thêm thư viện đó làm phần phụ thuộc kiểm thử:
testImplementation("androidx.health.connect:connect-testing:1.0.0-alpha01")
Điểm truy cập vào thư viện là lớp FakeHealthConnectClient
mà bạn dùng trong các chương trình kiểm thử để thay thế HealthConnectClient
. FakeHealthConnectClient
có các tính năng sau:
- Một bản trình bày trong bộ nhớ của các bản ghi, vì vậy bạn có thể chèn, xoá và đọc các bản ghi đó
- Tạo mã thông báo thay đổi và theo dõi thay đổi
- Phân trang cho bản ghi và thay đổi
- Các phản hồi tổng hợp được hỗ trợ bằng các phần giữ chỗ
- Cho phép mọi hàm tạo ra các trường hợp ngoại lệ
- Một
FakePermissionController
có thể dùng để mô phỏng các quy trình kiểm tra quyền
Để tìm hiểu thêm về cách thay thế các phần phụ thuộc trong quá trình kiểm thử, hãy đọc bài viết Chèn phần phụ thuộc trong Android. Để biết thêm về đối tượng giả, hãy đọc bài viết Dùng đối tượng kiểm thử trong Android.
Ví dụ: nếu lớp tương tác với ứng dụng có tên là HealthConnectManager
và lấy HealthConnectClient
làm phần phụ thuộc, thì lớp đó sẽ có dạng như sau:
class HealthConnectManager(
private val healthConnectClient: HealthConnectClient,
...
) { }
Trong các kiểm thử, bạn có thể truyền một dữ liệu giả vào lớp đang kiểm thử thay vì:
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)
}
}
Bài kiểm thử này xác minh rằng hàm fetchReport
giả định trong HealthConnectManager
lọc các bản ghi đúng cách theo hoạt động.
Xác minh các trường hợp ngoại lệ
Hầu như mọi lệnh gọi đến HealthConnectClient
đều có thể gửi các trường hợp ngoại lệ. Ví dụ: tài liệu cho insertRecords
đề cập đến những trường hợp ngoại lệ sau:
@throws android.os.RemoteException
cho mọi lỗi vận chuyển IPC.@throws SecurityException
đối với những yêu cầu không được phép truy cập.@throws java.io.IOException
đối với mọi vấn đề về I/O trên ổ đĩa.
Những trường hợp ngoại lệ này bao gồm các trường hợp như kết nối kém hoặc không còn dung lượng trên thiết bị. Ứng dụng của bạn phải phản ứng chính xác với những vấn đề trong thời gian chạy này, vì chúng có thể xảy ra bất cứ lúc nào.
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)
}
Tổng hợp
Các lệnh gọi tổng hợp không có quá trình triển khai giả. Thay vào đó, các lệnh gọi tổng hợp sử dụng các phần giữ chỗ mà bạn có thể lập trình để hoạt động theo một cách nhất định. Bạn có thể truy cập vào các phần giữ chỗ thông qua thuộc tính overrides
của FakeHealthConnectClient
.
Ví dụ: bạn có thể lập trình hàm tổng hợp để trả về một kết quả cụ thể:
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)
Sau đó, bạn có thể xác minh rằng lớp đang kiểm thử (HealthConnectManager
trong trường hợp này) đã xử lý kết quả một cách chính xác:
// 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)
Quyền
Thư viện kiểm thử có chứa một FakePermissionController
mà bạn có thể truyền dưới dạng một phần phụ thuộc đến FakeHealthConnectClient
.
Đối tượng kiểm thử có thể sử dụng PermissionController—through
thuộc tính permissionController
của giao diện HealthConnectClient
để kiểm tra quyền. Việc này thường được thực hiện trước mỗi lệnh gọi đến máy khách.
Để kiểm thử chức năng này, bạn có thể đặt những quyền có sẵn bằng cách sử dụng 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)
}
Phân trang
Phân trang là một nguồn lỗi rất phổ biến, vì vậy FakeHealthConnectClient
cung cấp các cơ chế giúp bạn xác minh rằng việc triển khai phân trang cho các bản ghi và thay đổi hoạt động đúng cách.
Đối tượng kiểm thử của bạn (HealthConnectManager
trong ví dụ của chúng tôi) có thể chỉ định kích thước trang trong ReadRecordsRequest
:
fun fetchRecordsReport(pageSize: Int = 1000) }
val pagedRequest =
ReadRecordsRequest(
timeRangeFilter = ...,
recordType = ...,
pageToken = page1.pageToken,
pageSize = pageSize,
)
val page = client.readRecords(pagedRequest)
...
Việc đặt kích thước trang thành một giá trị nhỏ, chẳng hạn như 2, cho phép bạn kiểm thử tính năng phân trang. Ví dụ: bạn có thể chèn 5 bản ghi để readRecords
trả về 3 trang riêng biệt:
@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)
}
Dữ liệu kiểm thử
Thư viện này chưa có các API để tạo dữ liệu giả, nhưng bạn có thể sử dụng dữ liệu và trình tạo mà thư viện này dùng trong Android Code Search.
Để mô phỏng các giá trị siêu dữ liệu trong các quy trình kiểm thử, bạn có thể sử dụng MetadataTestHelper
. Điều này cung cấp hàm mở rộng populatedWithTestValues()
, mô phỏng Health Connect điền các giá trị siêu dữ liệu trong quá trình chèn bản ghi.
Đầu mẩu
Thuộc tính overrides
của FakeHealthConnectClient
cho phép bạn lập trình (hoặc giả lập) bất kỳ hàm nào của nó để các hàm đó sẽ gửi ra các ngoại lệ khi được gọi.
Các lệnh gọi tổng hợp cũng có thể trả về dữ liệu tuỳ ý và hỗ trợ xếp hàng nhiều phản hồi. Hãy xem Stub
và MutableStub
để biết thêm thông tin.
Tóm tắt các trường hợp đặc biệt
- Xác minh rằng ứng dụng của bạn hoạt động như dự kiến khi ứng dụng gửi ra các trường hợp ngoại lệ. Hãy xem tài liệu của từng hàm để tìm ra những ngoại lệ mà bạn nên kiểm tra.
- Xác minh rằng mọi lệnh gọi bạn thực hiện đến ứng dụng đều được thực hiện trước khi kiểm tra quyền thích hợp.
- Xác minh việc triển khai tính năng phân trang.
- Xác minh điều gì sẽ xảy ra khi bạn tìm nạp nhiều trang nhưng một trang có mã thông báo đã hết hạn.