<पी> पिछले लेख में, मैंने बताया था कि आप अपने एप्लिकेशन में प्रोटो डेटास्टोर का उपयोग कैसे कर सकते हैं। मैंने वह लेख अपने एक एप्लिकेशन में प्रोटो डेटास्टोर का उपयोग करने के अपने अनुभव के हिस्से के रूप में लिखा था। <पी> उसके बाद, मैं यह देखना चाहता था कि मेरे द्वारा प्राप्त ज्ञान का उपयोग करके उस एप्लिकेशन में प्रोटो डेटास्टोर के लिए परीक्षण लिखना कैसा होगा। पी> <पी> मार्गदर्शन के लिए ऑनलाइन खोज करने से ज्यादा राहत नहीं मिली, इसलिए मैंने सोचा कि मैं अपना ज्ञान उन लोगों के साथ साझा करूंगा जो इसकी तलाश में हैं। सबसे बुरी स्थिति में, यह मेरी संतान के लिए होगा। <पी> अपनी खोज में, मुझे यह लेख मिला, लेकिन यह अधिकतर प्रेफरेंस डेटास्टोर के परीक्षण पर केंद्रित है न कि प्रोटो डेटास्टोर पर। इसमें कहा गया है कि: <पी> “हालांकि, ध्यान रखें कि आप इस सामग्री का उपयोग प्रोटो डेटास्टोर स्थापित करने के लिए कर सकते हैं परीक्षण, क्योंकि यह प्राथमिकताओं के समान ही होगा।'' <पी> लेकिन इसका अनुसरण करने पर, मुझे पता चला कि निर्भरताओं के अलावा, यहां कई समानताएं नहीं हैं और आपको अपने स्वयं के प्रोटो डेटास्टोर का परीक्षण करने के लिए अलग तर्क पेश करने की आवश्यकता है। चीजें व्यवस्थित करना
<पी> अपने एप्लिकेशन की बिल्ड.ग्रेडल फ़ाइल में, निम्नलिखित निर्भरताएँ जोड़ें: dependencies {
///.....
androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
debugImplementation "androidx.compose.ui:ui-test-manifest:$compose_version"
}
<पी> $compose_version वह वेरिएबल है जिसे आपने अपने प्रोजेक्ट लेवल बिल्ड.ग्रेडल फ़ाइल में परिभाषित किया है। <पी> फिर, अपने androidTest पर जाएं निर्देशिका बनाएं और एक नई फ़ाइल बनाएं। आमतौर पर, आपके पास एक रिपॉजिटरी क्लास होगी जो आपके प्रोटो डेटास्टोर के साथ इंटरैक्ट करती है, इसलिए आप इस फ़ाइल को YourRepositoryClassNameTest नाम दे सकते हैं। हम MyRepositoryTest नाम का उपयोग करेंगे . <पी> इससे पहले कि हम प्रोटो डेटास्टोर का परीक्षण करें, हमें इसे तत्काल करने की आवश्यकता है। यदि आप इस पर कोई दस्तावेज़ खोजने के लिए ऑनलाइन जाते हैं, तो यह थोड़ा विरल है। पी> <पी> प्रोटो डेटास्टोर को इंस्टेंटिएट करने का उपयोग वैश्विक संदर्भ के साथ किया जाता है (जब परीक्षण परिदृश्य में उपयोग नहीं किया जाता है): private val Context.myDataStore: DataStore<MyItem> by dataStore(
fileName = DATA_STORE_FILE_NAME,
serializer = MyItemSerializer
)
<पी> ठीक है, आप इसे परीक्षण कक्षा के अंदर नहीं कर सकते, क्योंकि, यद्यपि आप उपरोक्त कोड को कॉपी-पेस्ट कर सकते हैं, आप ऐसा नहीं कर पाएंगे पहुँच डेटास्टोर ऑब्जेक्ट। आप एप्लिकेशन संदर्भ इस प्रकार प्राप्त कर सकते हैं: ApplicationProvider.getApplicationContext()
<पी> लेकिन हमारा myDataStore इसके माध्यम से वस्तु उपलब्ध नहीं होगी। <पी> तो, हम क्या कर सकते हैं? <पी> ऊपर लिंक किए गए आलेख में, एक उदाहरण है कि हम PreferenceDataStoreFactory.create विधि का उपयोग करके एक Preference DataStore कैसे बना सकते हैं। fun create(
corruptionHandler: ReplaceFileCorruptionHandler<Preferences>? = null,
migrations: List<DataMigration<Preferences>> = listOf(),
scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob()),
produceFile: () -> File): DataStore<Preferences>
<पी> लेकिन चूंकि हम प्रेफरेंस डेटास्टोर का उपयोग नहीं कर रहे हैं, इसलिए यह हमारे लिए काम नहीं करेगा। DataStoreFactory.create विधि का इस प्रकार उपयोग करना काम करेगा: fun <T : Any?> create(
serializer: Serializer<T>,
corruptionHandler: ReplaceFileCorruptionHandler<T>? = null,
migrations: List<DataMigration<T>> = listOf(),
scope: CoroutineScope = CoroutineScope(Dispatchers.IO + SupervisorJob()), produceFile: () -> File): DataStore<T>
<पी> इस पद्धति के लिए कई तर्क हैं (और कुछ में डिफ़ॉल्ट मान हैं), लेकिन हमें उन सभी को पारित करने की आवश्यकता नहीं है। हम पारित करेंगे: - हमारा सीरिएलाइज़र वर्ग
- हमारे प्रोटो डेटास्टोर के लिए फ़ाइल बनाने के लिए एक लैम्ब्डा विधि
dataStore = DataStoreFactory.create(
produceFile = {
testContext.dataStoreFile(TEST_DATA_STORE_FILE_NAME) },
serializer = MyItemSerializer
)
<पी> हमें testContext मिलता है द्वारा: private val testContext: Context = ApplicationProvider.getApplicationContext()
<पी> अपना प्रोटो डेटास्टोर सफलतापूर्वक बनाने के बाद, हम इसके लिए कुछ परीक्षण लिखने के लिए आगे बढ़ सकते हैं। ध्यान रखें कि आपके पास एक रिपॉजिटरी क्लास है जो निर्भरता के रूप में प्रोटो डेटास्टोर का उदाहरण प्राप्त करती है, इसलिए प्रोटो डेटास्टोर बनाने के बाद, हमें अपने रिपॉजिटरी क्लास का एक उदाहरण बनाने की आवश्यकता है। private val repository = MyRepository(datastore)
<पी> सबसे पहले, आइए अपनी प्रारंभिक प्रोटो डेटास्टोर स्थिति की जांच करने के लिए एक परीक्षण बनाएं। प्रोटो डेटास्टोर स्वयं एक प्रवाह को उजागर करता है जिसका हम उपयोग कर सकते हैं। @OptIn(ExperimentalCoroutinesApi::class)
@Test
fun repository_testFetchInitialState() {
runTest {
testScope.launch {
val dataStoreObject = repository.myFlow.first()
// Insert here whatever we want to assert from our
// Proto DataStore. I.E. a flag whose initial value is false
assert(dataStoreObject.myFlag == false)
}
}
}
<पी> ☝️ आपने इसे पहले देखा होगा, लेकिन हम एक ऑप्टइन एनोटेशन का उपयोग कर रहे हैं यहाँ. ऐसा इसलिए है क्योंकि (वर्तमान में) जो एपीआई हम उपयोग कर रहे हैं वे प्रयोगात्मक हैं और जब हम उनका उपयोग करते हैं तो उन्हें चिह्नित किया जाना चाहिए। <पी> चूँकि हम अपने DataStore के प्रवाह तक पहुँच रहे हैं , हमें इसे अपने testScope में लपेटना होगा . TestScope ऐसा करने से बनता है: @OptIn(ExperimentalCoroutinesApi::class)
private val dispatcher = TestCoroutineDispatcher()
@OptIn(ExperimentalCoroutinesApi::class)
private val testScope = TestCoroutineScope(dispatcher)
<पी> इसे चलाएं और अपने पहले प्रोटो डेटास्टोर परीक्षण का आनंद लें। <पी> वह लगभग दो सेकंड के लिए मज़ेदार था। <पी> आइए कुछ और सार्थक करें। <पी> कल्पना करें कि हमारे प्रोटो डेटास्टोर के अंदर वस्तुओं की एक सूची है और जब हम इसमें कोई आइटम जोड़ते हैं तो हम इसकी स्थिति का परीक्षण करना चाहते हैं। @OptIn(ExperimentalCoroutinesApi::class)
@Test
fun repository_testAdditionOfItem() {
runTest {
testScope.launch {
//1
val item: MyItem = MyItem.newBuilder().setItemId(UUID.randomUUID().toString())
.setItemDescription(TEST_ITEM_DESCRIPTION).build()
//2
repository.updateItem(item)
//3
val items = repository.myFlow.first().itemsList
assert(items.size == 1)
//4
assert(items[0].itemDescription.equals(TEST_ITEM_DESCRIPTION))
}
}
}
- हम प्रोटोबफ़ से एक्सपोज़्ड एपीआई का उपयोग करके एक परीक्षण आइटम बनाते हैं
- हम MyRepository क्लास में प्रदर्शित विधि का उपयोग करके इस आइटम को प्रोटो डेटास्टोर में जोड़ते हैं
- हम प्रोटो डेटास्टोर द्वारा उजागर किए गए प्रवाह से आइटमों की सूची लेते हैं
- हम यह सुनिश्चित करते हैं कि प्रोटो डेटास्टोर में पाया गया आइटम हमारे द्वारा पहले बनाए गए आइटम से मेल खाता है
आपके डेटास्टोर में लीक है
<पी> यदि आप उपरोक्त परीक्षणों को एक बार में चलाने का प्रयास करते हैं, तो आपको जल्द ही रनटाइम के दौरान एक त्रुटि प्राप्त होगी: <पी> एक ही फ़ाइल के लिए कई डेटास्टोर सक्रिय हैं:/data/user/0/com.example.app/files/datastore/dataStore_filename.pb. आपको या तो अपने डेटास्टोर को सिंगलटन के रूप में बनाए रखना चाहिए या पुष्टि करनी चाहिए कि एक ही फ़ाइल पर दो डेटास्टोर सक्रिय नहीं हैं (यह पुष्टि करके कि दायरा रद्द कर दिया गया है)। <पी> ख़ैर, यह समस्याग्रस्त है। हमने अपनी परीक्षण कक्षा में केवल एक डेटास्टोर इंस्टेंस बनाया है। <पी> यहाँ क्या हो रहा है? <पी> क्योंकि हम अपना डेटास्टोर (मतलब कॉन्टेक्स्ट.डेटास्टोर) बनाने के लिए प्रॉपर्टी डेलिगेट का उपयोग नहीं कर रहे हैं, यह सुनिश्चित नहीं है कि जब भी हम इसे एक्सेस करते हैं तो हमारा डेटास्टोर ऑब्जेक्ट सिंगलटन होता है। <पी> इस परिदृश्य से बचने के लिए, मुझे पता चला है कि प्रत्येक परीक्षण मामले के लिए डेटास्टोर को हटाना और पुनः बनाना एक तरीका है। डेटास्टोर को हटाने के लिए, हम यह कर सकते हैं: @After
fun cleanup() {
File(testContext.filesDir, "datastore").deleteRecursively()
}
<पी> और प्रत्येक परीक्षण से पहले, हम इसे पुनः बनाते हैं: @Before
fun setup() {
dataStore = DataStoreFactory.create(
produceFile = {
testContext.dataStoreFile(TEST_DATA_STORE_FILE_NAME)
},
serializer = MyItemSerializer
)
}
<पी> पूरा उदाहरण देखने के लिए, आप यहां जा सकते हैं। <पी> इस आलेख में, मैं एक प्रोटो डेटास्टोर का परीक्षण कैसे किया जा सकता है इसकी रूपरेखा दिखाना चाहता था। पी> <पी> जबकि मैंने आपके डेटास्टोर और आपके द्वारा वहां कॉन्फ़िगर किए गए प्रकारों के आधार पर दो परीक्षण मामलों का अवलोकन किया, लिखने के लिए और अधिक परीक्षण मामले और परिदृश्य हो सकते हैं। बिल्डिंग ब्लॉक्स वहां मौजूद हैं, आपको बस इसे अपनी आवश्यकताओं के अनुरूप ढालना है। <पी> मुफ़्त में कोड करना सीखें. फ्रीकोडकैंप के ओपन सोर्स पाठ्यक्रम ने 40,000 से अधिक लोगों को डेवलपर्स के रूप में नौकरी पाने में मदद की है। आरंभ करें