Health Connect की टेस्टिंग लाइब्रेरी का इस्तेमाल करके यूनिट टेस्ट बनाना

Health Connect की टेस्टिंग लाइब्रेरी (androidx.health.connect:connect-testing) की मदद से, ऑटोमेटेड टेस्ट आसानी से बनाए जा सकते हैं. इस लाइब्रेरी का इस्तेमाल करके, अपने ऐप्लिकेशन के व्यवहार की पुष्टि की जा सकती है. साथ ही, यह पुष्टि की जा सकती है कि यह उन असामान्य मामलों में सही तरीके से काम कर रहा है जिनकी जांच मैन्युअल तरीके से करना मुश्किल होता है.

इस लाइब्रेरी का इस्तेमाल करके, लोकल यूनिट टेस्ट बनाए जा सकते हैं. ये आम तौर पर, आपके ऐप्लिकेशन में मौजूद उन क्लास के व्यवहार की पुष्टि करते हैं जो Health Connect क्लाइंट के साथ इंटरैक्ट करती हैं.

लाइब्रेरी का इस्तेमाल शुरू करने के लिए, इसे टेस्ट डिपेंडेंसी के तौर पर जोड़ें:

 testImplementation("androidx.health.connect:connect-testing:1.0.0-alpha01")

लाइब्रेरी का एंट्री पॉइंट FakeHealthConnectClient क्लास है. इसका इस्तेमाल टेस्ट में HealthConnectClient को बदलने के लिए किया जाता है. FakeHealthConnectClient में ये सुविधाएं हैं:

  • रिकॉर्ड का इन-मेमोरी प्रज़ेंटेशन, ताकि उन्हें डाला, हटाया, मिटाया, और पढ़ा जा सके
  • बदलाव के टोकन जनरेट करना और बदलावों को ट्रैक करना
  • रिकॉर्ड और बदलावों के लिए पेज नंबर डालना
  • स्टब के साथ एग्रीगेशन के जवाब दिए जा सकते हैं
  • इससे किसी भी फ़ंक्शन को अपवादों को थ्रो करने की अनुमति मिलती है
  • एक FakePermissionController, जिसका इस्तेमाल अनुमतियों की जांच करने के लिए किया जा सकता है

टेस्ट में डिपेंडेंसी बदलने के बारे में ज़्यादा जानने के लिए, Android में डिपेंडेंसी इंजेक्शन लेख पढ़ें. फ़ेक के बारे में ज़्यादा जानने के लिए, 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)
    }
}

इस टेस्ट से यह पुष्टि की जाती है कि HealthConnectManager में मौजूद काल्पनिक fetchReport फ़ंक्शन, गतिविधि के हिसाब से रिकॉर्ड को सही तरीके से फ़िल्टर करता है.

अपवादों की पुष्टि की जा रही है

HealthConnectClient को किए गए लगभग हर कॉल में अपवाद हो सकते हैं. उदाहरण के लिए, insertRecords के दस्तावेज़ में इन अपवादों के बारे में बताया गया है:

  • @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)
}

एक साथ दिखाना

एग्रीगेशन कॉल में फ़र्ज़ी तरीके से लागू करने की सुविधा नहीं होती. इसके बजाय, एग्रीगेशन कॉल ऐसे स्टब का इस्तेमाल करते हैं जिन्हें किसी खास तरीके से काम करने के लिए प्रोग्राम किया जा सकता है. स्टब को FakeHealthConnectClient की overrides प्रॉपर्टी के ज़रिए ऐक्सेस किया जा सकता है.

उदाहरण के लिए, एग्रीगेट फ़ंक्शन को प्रोग्राम करके, कोई खास नतीजा पाया जा सकता है:

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 में डिपेंडेंसी के तौर पर पास किया जा सकता है.

जांच में शामिल विषय, अनुमतियों की जांच करने के लिए HealthConnectClient इंटरफ़ेस की PermissionController—through permissionController प्रॉपर्टी का इस्तेमाल कर सकता है. आम तौर पर, क्लाइंट को कॉल करने से पहले ऐसा किया जाता है.

इस सुविधा को आज़माने के लिए, 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 जैसी छोटी वैल्यू पर सेट करने से, पेज नंबर डालने की सुविधा को टेस्ट किया जा सकता है. उदाहरण के लिए, पांच रिकॉर्ड डाले जा सकते हैं, ताकि readRecords तीन अलग-अलग पेज दिखाए:

@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)
}

टेस्ट डेटा

इस लाइब्रेरी में फ़िलहाल, नकली डेटा जनरेट करने के लिए एपीआई शामिल नहीं हैं. हालांकि, Android Code Search में लाइब्रेरी के इस्तेमाल किए गए डेटा और जनरेटर का इस्तेमाल किया जा सकता है.

जांच में मेटाडेटा वैल्यू को मॉक करने के लिए, MetadataTestHelper का इस्तेमाल किया जा सकता है. इससे populatedWithTestValues() एक्सटेंशन फ़ंक्शन मिलता है. यह फ़ंक्शन, रिकॉर्ड डालने के दौरान Health Connect के मेटाडेटा की वैल्यू को भरने की प्रोसेस को सिम्युलेट करता है.

स्टब

FakeHealthConnectClient की overrides प्रॉपर्टी की मदद से, इसके किसी भी फ़ंक्शन को प्रोग्राम किया जा सकता है. इसके अलावा, इसे स्टब आउट किया जा सकता है, ताकि कॉल किए जाने पर ये अपवाद दिखाएं. एग्रीगेशन कॉल, कोई भी डेटा दिखा सकते हैं. साथ ही, यह एक साथ कई जवाबों को लाइन में लगाने की सुविधा देता है. ज़्यादा जानकारी के लिए, Stub और MutableStub देखें.

कभी-कभी होने वाले मामलों की खास जानकारी

  • पुष्टि करें कि क्लाइंट के अपवादों को खारिज करने पर, आपका ऐप्लिकेशन उम्मीद के मुताबिक काम करता है. हर फ़ंक्शन के दस्तावेज़ देखें. इससे आपको यह पता चलेगा कि आपको किन अपवादों की जांच करनी चाहिए.
  • पुष्टि करें कि क्लाइंट को किए जाने वाले हर कॉल से पहले, अनुमतियों की सही तरीके से जांच की गई हो.
  • पुष्टि करें कि आपने पेज नंबर के हिसाब से कॉन्टेंट दिखाने की सुविधा लागू की है.
  • पुष्टि करें कि एक साथ कई पेजों को फ़ेच करने पर क्या होता है, जबकि उनमें से किसी एक पेज का टोकन खत्म हो गया हो.