کتابخانه Health Connect Testing ( androidx.health.connect:connect-testing
) ایجاد تستهای خودکار را ساده میکند. میتوانید از این کتابخانه برای تأیید رفتار برنامهتان و تأیید درستی پاسخ صحیح آن به موارد غیرمعمول، که آزمایش دستی آنها سخت است، استفاده کنید.
میتوانید از کتابخانه برای ایجاد آزمایشهای واحد محلی استفاده کنید، که معمولاً رفتار کلاسهایی را که در برنامه شما با کلاینت Health Connect تعامل دارند تأیید میکنند.
برای شروع استفاده از کتابخانه، آن را به عنوان وابستگی آزمایشی اضافه کنید:
testImplementation("androidx.health.connect:connect-testing:1.0.0-alpha01")
نقطه ورود به کتابخانه کلاس FakeHealthConnectClient
است که در آزمایشات جایگزین HealthConnectClient
استفاده می کنید. FakeHealthConnectClient
دارای ویژگی های زیر است:
- نمایشی از رکوردها در حافظه، بنابراین می توانید آنها را درج، حذف، حذف و بخوانید
- تولید نشانه های تغییر و ردیابی تغییر
- صفحه بندی برای سوابق و تغییرات
- پاسخهای انباشتگی با خرد پشتیبانی میشوند
- به هر تابعی اجازه می دهد تا استثناها را ایجاد کند
- یک
FakePermissionController
که می تواند برای شبیه سازی بررسی های مجوز استفاده شود
برای کسب اطلاعات بیشتر در مورد جایگزینی وابستگی ها در تست ها، Dependency Injection را در 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
. -
@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)
}
تجمع
فراخوانی های تجمیع پیاده سازی های جعلی ندارند. درعوض، فراخوانیهای انباشته از خردههایی استفاده میکنند که میتوانید برای رفتار به روشی برنامهریزی کنید. شما میتوانید از طریق ویژگی overrides
FakeHealthConnectClient
به خردهها دسترسی داشته باشید.
برای مثال، میتوانید تابع aggregate را برای برگرداندن یک نتیجه خاص برنامهریزی کنید:
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
ویژگی permissionController
در رابط HealthConnectClient
- برای بررسی مجوزها استفاده کند. این معمولاً قبل از هر تماس با مشتری انجام می شود.
برای آزمایش این عملکرد، می توانید با استفاده از 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
مکانیسمهایی را ارائه میکند تا به شما کمک کند تا بررسی کنید که پیادهسازی صفحهبندی شما برای رکوردها و تغییرات به درستی عمل میکند.
موضوع مورد آزمایش شما، HealthConnectManager
در مثال ما، می تواند اندازه صفحه را در ReadRecordsRequest
مشخص کند:
fun fetchRecordsReport(pageSize: Int = 1000) }
val pagedRequest =
ReadRecordsRequest(
timeRangeFilter = ...,
recordType = ...,
pageToken = page1.pageToken,
pageSize = pageSize,
)
val page = client.readRecords(pagedRequest)
...
تنظیم اندازه صفحه روی یک مقدار کوچک، مانند 2، به شما امکان می دهد صفحه بندی را به راحتی آزمایش کنید. به عنوان مثال، می توانید 5 رکورد را وارد کنید تا readRecords
3 صفحه مختلف را برگرداند:
@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 استفاده کنید.
خرد
ویژگی overrides
FakeHealthConnectClient
به شما امکان می دهد هر یک از توابع آن را برنامه ریزی کنید (یا خرد کنید ) تا در هنگام فراخوانی استثناهایی ایجاد کنند. تماسهای انباشته همچنین میتوانند دادههای دلخواه را برگردانند و از قرار دادن پاسخهای متعدد در صف پشتیبانی میکنند. برای اطلاعات بیشتر به Stub
و MutableStub
مراجعه کنید.
خلاصه ای از موارد لبه
- بررسی کنید که برنامه شما همانطور که انتظار می رود در زمانی که سرویس گیرنده موارد استثنا را ایجاد می کند، رفتار می کند. مستندات هر تابع را بررسی کنید تا متوجه شوید چه استثناهایی را باید بررسی کنید.
- بررسی کنید که قبل از هر تماسی که با مشتری برقرار می کنید، بررسی مجوزهای مناسب انجام شود.
- اجرای صفحه بندی خود را تأیید کنید.
- بررسی کنید وقتی چندین صفحه واکشی میکنید اما یکی از آنها توکن منقضی شده دارد چه اتفاقی میافتد.