जांच की बुनियादी बातें

यह कोडलैब, Kotlin में बेहतर Android का हिस्सा है. अगर आप कोडलैब के क्रम में काम करते हैं, लेकिन यह ज़रूरी नहीं है, तो आपको इस कोर्स का पूरा फ़ायदा मिलेगा. सभी कोर्स कोडलैब Kotlin कोडलैब के लैंडिंग पेज पर बेहतर Android पेज पर दिए गए हैं.

परिचय

जब आपने अपने पहले ऐप्लिकेशन की पहली सुविधा लागू की थी, तो हो सकता है कि आपने कोड चलाकर यह पुष्टि की हो कि वह उम्मीद के मुताबिक काम कर रहा है. आपने टेस्ट किया, हालांकि मैन्युअल टेस्ट किया. जैसे-जैसे आप सुविधाएं जोड़ते और अपडेट करते जाएंगे, आपका कोड भी चलता रहेगा और उसकी पुष्टि होती रहेगी. हालांकि, मैन्युअल रूप से हर बार ऐसा करते समय आप थकावट करते हैं, गलतियां करते हैं, और यह बड़े पैमाने पर नहीं होता है.

कंप्यूटर स्केलिंग और ऑटोमेशन में बहुत अच्छे हैं! इसलिए, बड़ी और छोटी कंपनियों के डेवलपर अपने-आप होने वाली जांच लिखते हैं, जो कि ऐसी जांच होती हैं जिन्हें सॉफ़्टवेयर चलाता है और जिनके लिए आपको कोड के काम की पुष्टि करने के लिए ऐप्लिकेशन को मैन्युअल तरीके से चलाने की ज़रूरत नहीं होती.

कोडलैब की इस सीरीज़ में आप क्या सीख सकते हैं, यह सीखना है कि असल दुनिया में मौजूद ऐप्लिकेशन के लिए, टेस्ट का संग्रह कैसे बनाते हैं (इसे टेस्टिंग सुइट) के नाम से जाना जाता है.

इस पहले कोडलैब में Android पर जांच से जुड़ी बुनियादी बातें शामिल हैं, आप अपनी पहली जांच लिखेंगे और LiveData और ViewModel की जांच करने का तरीका जानेंगे.

आपको क्या पता होना चाहिए

आपको इनके बारे में पता होना चाहिए:

आप इन चीज़ों के बारे में जानेंगे

आपको इन विषयों के बारे में जानकारी मिलेगी:

  • Android पर इकाई की जांच लिखने और चलाने का तरीका
  • टेस्ट ड्राइव्ड डेवलपमेंट का इस्तेमाल कैसे करें
  • इंस्ट्रूमेंटल टेस्ट और स्थानीय टेस्ट चुनने का तरीका

आपको नीचे दी गई लाइब्रेरी और कोड के सिद्धांतों के बारे में जानकारी मिलेगी:

आप क्या कर पाएंगे!

  • Android में स्थानीय और इंस्ट्रुमेंटेड टेस्ट, दोनों को सेट अप करें, चलाएं, और समझें.
  • JUnit4 और Hamcrest का इस्तेमाल करके Android में यूनिट की जांच लिखें.
  • आसान LiveData और ViewModel टेस्ट लिखें.

कोडलैब की इस सीरीज़ में, आप काम की सूची के नोट के साथ काम करेंगे. इस ऐप्लिकेशन की मदद से, आप टास्क पूरे कर सकते हैं और उन्हें सूची में दिखा सकते हैं. इसके बाद, आप इन्हें 'पूरा हुआ' या 'नहीं' के तौर पर मार्क कर सकते हैं. साथ ही, आप इन्हें फ़िल्टर कर सकते हैं या मिटा भी सकते हैं.

यह ऐप्लिकेशन Kotlin में लिखा गया है, इसमें कई स्क्रीन हैं, Jetpack कॉम्पोनेंट का इस्तेमाल करते हैं, और ऐप्लिकेशन आर्किटेक्चर की गाइड के आर्किटेक्चर का पालन करते हैं. इस ऐप्लिकेशन की जांच करने का तरीका देखकर, आप एक ही लाइब्रेरी और आर्किटेक्चर का इस्तेमाल करने वाले ऐप्लिकेशन की जांच कर सकते हैं.

शुरू करने के लिए, कोड डाउनलोड करें:

पिन डाउनलोड करें

इसके अलावा, आप कोड के लिए GitHub डेटा स्टोर करने की जगह को क्लोन कर सकते हैं:

$ git clone https://github.com/googlecodelabs/android-testing.git
$ cd android-testing
$ git checkout starter_code

इस टास्क में आप ऐप्लिकेशन को चलाएंगे #39; और कोड बेस को एक्सप्लोर करेगा.

पहला चरण: सैंपल ऐप्लिकेशन चलाना

एक बार TO-Do ऐप्लिकेशन डाउनलोड कर लेने के बाद, इसे Android Studio में खोलें और चलाएं. यह कंपाइल होना चाहिए. नीचे दिए गए काम करके ऐप्लिकेशन को एक्सप्लोर करें:

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

दूसरा चरण: ऐप्लिकेशन के नमूने का कोड एक्सप्लोर करना

काम की सूची वाला ऐप्लिकेशन, लोकप्रिय आर्किटेक्चर ब्लूप्रिंट टेस्टिंग और आर्किटेक्चर सैंपल पर आधारित है (सैंपल के रिऐक्टिव आर्किटेक्चरल वर्शन का इस्तेमाल करके). ऐप्लिकेशन, ऐप्लिकेशन के आर्किटेक्चर की गाइड में दिए गए आर्किटेक्चर का पालन करता है. यह फ़्रैगमेंट, डेटा स्टोर करने की जगह, और रूम वाले ViewModels का इस्तेमाल करता है. अगर आप इन उदाहरणों में से किसी एक के बारे में जानते हैं, तो इस ऐप्लिकेशन का आर्किटेक्चर भी ऐसा ही है:

किसी खास लेयर के लॉजिक की पूरी जानकारी देने के बजाय, यह ज़रूरी है कि आप ऐप्लिकेशन की सामान्य आर्किटेक्चर को समझें.

यहां उन पैकेज की खास जानकारी दी गई है, जिन्हें आप #39:

पैकेज: com.example.android.architecture.blueprints.todoapp

.addedittask

टास्क की स्क्रीन जोड़ना या उसमें बदलाव करना: किसी टास्क को जोड़ने या उसमें बदलाव करने के लिए, यूज़र इंटरफ़ेस (यूआई) का लेयर कोड.

.data

डेटा लेयर: यह टास्क के डेटा लेयर से जुड़ा होता है. इसमें डेटाबेस, नेटवर्क, और रिपॉज़िटरी कोड शामिल होता है.

.statistics

आंकड़ों की स्क्रीन: आंकड़ों की स्क्रीन के लिए यूज़र इंटरफ़ेस (यूआई) कोड.

.taskdetail

टास्क की जानकारी वाली स्क्रीन: किसी एक टास्क के लिए यूज़र इंटरफ़ेस (यूआई) का लेयर कोड.

.tasks

टास्क टास्क: सभी टास्क की सूची के लिए यूज़र इंटरफ़ेस (यूआई) का कोड.

.util

उपयोगिता क्लास: ऐप्लिकेशन के अलग-अलग हिस्सों में इस्तेमाल की जाने वाली 'शेयर की गई क्लास', जैसे कि एक से ज़्यादा स्क्रीन पर इस्तेमाल किए जाने वाले स्वाइप रीफ़्रेश लेआउट के लिए.

डेटा स्तर (.data)

इस ऐप्लिकेशन में, रिमोट पैकेज में एक सिम्युलेटेड नेटवर्किंग लेयर और लोकल पैकेज में एक डेटाबेस लेयर शामिल होती है. आसानी से कहें, तो इस प्रोजेक्ट में नेटवर्किंग लेयर को असल नेटवर्क अनुरोध करने के बजाय, देरी से सिर्फ़ HashMap के साथ सिम्युलेट किया जाता है.

DefaultTasksRepository नेटवर्किंग लेयर और डेटाबेस लेयर के बीच निर्देशांक या मीडिएट करता है. साथ ही, यह यूआई लेयर में डेटा दिखाता है.

यूज़र इंटरफ़ेस (यूआई) लेयर ( .addedittask, .आंकड़े, .taskdetail, .tasks)

हर यूज़र इंटरफ़ेस (यूआई) लेयर पैकेज में एक फ़्रैगमेंट और एक व्यू मॉडल होता है. इसके अलावा, यूज़र इंटरफ़ेस (यूआई) के लिए ज़रूरी अन्य क्लास भी होती हैं (जैसे कि टास्क सूची के लिए कोई अडैप्टर). TaskActivity वह गतिविधि है जिसमें सभी फ़्रैगमेंट शामिल होते हैं.

नेविगेशन

ऐप्लिकेशन के लिए नेविगेशन को नेविगेशन कॉम्पोनेंट से कंट्रोल किया जाता है. यह nav_graph.xml फ़ाइल में बताया गया है. नेविगेशन Event क्लास का इस्तेमाल करके व्यू मॉडल में ट्रिगर होता है; व्यू मॉडल यह भी तय करते हैं कि कौनसे पास करने हैं. फ़्रैगमेंट Event की निगरानी करते हैं और स्क्रीन के बीच असल नेविगेशन करते हैं.

इस टास्क में, आप #39;अपना पहला टेस्ट चलाएं.

  1. Android Studio में, प्रोजेक्ट पैनल खोलें और इन तीन फ़ोल्डर को खोजें:
  • com.example.android.architecture.blueprints.todoapp
  • com.example.android.architecture.blueprints.todoapp (androidTest)
  • com.example.android.architecture.blueprints.todoapp (test)

इन फ़ोल्डर को स्रोत सेट के नाम से जाना जाता है. सोर्स सेट ऐसे फ़ोल्डर होते हैं जिनमें आपके ऐप्लिकेशन का सोर्स कोड होता है. सोर्स सेट, जो हरे रंग के (androidTest और टेस्ट) होते हैं उनमें आपकी जांच शामिल होती है. नया Android प्रोजेक्ट बनाने पर, आपको डिफ़ॉल्ट रूप से ये तीन सोर्स सेट मिलते हैं. ये वजह हैं:

  • main: इसमें आपका ऐप्लिकेशन कोड शामिल होता है. यह कोड, ऐप्लिकेशन के सभी अलग-अलग वर्शन में शेयर किया जाता है. इन्हें वर्शन बिल्ड वैरिएंट कहा जाता है
  • androidTest: इसमें इंस्ट्रुमेंटल टेस्ट के तौर पर जाने वाले टेस्ट शामिल हैं.
  • test: इसमें स्थानीय जांचों से जुड़ी जांच शामिल होती है.

स्थानीय टेस्ट और काम करने वाले टेस्ट के बीच अंतर, उनके काम करने के तरीके के हिसाब से होता है.

लोकल टेस्ट (test सोर्स सेट)

ये टेस्ट, आपके डेवलपमेंट मशीन's JVM पर चलाए जाते हैं और इन्हें एम्युलेटर या फ़िज़िकल डिवाइस की ज़रूरत नहीं होती. इस वजह से, वे तेज़ दौड़ते हैं, लेकिन उनकी फ़िडेलिटी कम है. इसका मतलब है कि वे असल दुनिया की तरह कम काम करते हैं.

Android Studio में स्थानीय जांचों को हरे और लाल त्रिभुज के आइकॉन से दिखाया जाता है.

इंस्ट्रूमेंटल टेस्ट (androidTest सोर्स सेट)

ये टेस्ट, असली या एम्युलेट किए गए Android डिवाइसों पर चलाए जाते हैं. इसलिए, इनसे पता चलता है कि असल में क्या होगा, लेकिन ये धीरे काम करते हैं.

Android Studio की मदद से तैयार की गई जांचों में, Android को हरे और लाल त्रिभुज के आइकॉन के साथ दिखाया जाता है.

पहला चरण: स्थानीय जांच करना

  1. test फ़ोल्डर को तब तक खोलें, जब तक आपको ExampleUnitTest.kt फ़ाइल नहीं मिल जाती.
  2. इस पर दायां क्लिक करें और ExampleUnitTest चलाएं चुनें.

आपको स्क्रीन के सबसे नीचे, चलाएं विंडो में यह आउटपुट दिखेगा:

  1. हरे चेकमार्क पर ध्यान दें और जांच के नतीजों को बड़ा करके यह पक्का करें कि addition_isCorrect नाम की एक जांच पास हो चुकी है. यह जानकर अच्छा लगता है कि डेटा जोड़ा जाना उम्मीद के मुताबिक है!

दूसरा चरण: जांच फ़ेल होना

नीचे वह टेस्ट दिया गया है जिसे आपने अभी-अभी चलाया है.

ExampleUnitTest.kt

// A test class is just a normal class
class ExampleUnitTest {

   // Each test is annotated with @Test (this is a Junit annotation)
   @Test
   fun addition_isCorrect() {
       // Here you are checking that 4 is the same as 2+2
       assertEquals(4, 2 + 2)
   }
}

ध्यान दें कि जांच करना

  • टेस्ट सोर्स सेट में से एक में क्लास है.
  • इसमें ऐसे फ़ंक्शन शामिल हैं जो @Test एनोटेशन से शुरू होते हैं (हर फ़ंक्शन एक टेस्ट होता है).
  • इसमें, दावा करने वाले स्टेटमेंट शामिल हो सकते हैं.

Android, टेस्टिंग लाइब्रेरी के लिए JUnit का इस्तेमाल करता है. इसे कोडलैब JUnit4 में इस्तेमाल किया जा सकता है. दावे और @Test एनोटेशन, दोनों JUnit से आते हैं.

जांच, आपकी जांच का मुख्य हिस्सा है. यह एक कोड स्टेटमेंट है जो यह जांच करता है कि आपके कोड या ऐप्लिकेशन ने उम्मीद के मुताबिक काम किया है. इस मामले में, यह दावा assertEquals(4, 2 + 2) होता है, जो यह जांच करता है कि 4, 2 + 2 के बराबर है.

यह देखने के लिए कि फ़ेल हो चुकी जांच कैसी दिखती है, कोई ऐसा दावा जोड़ें जिसे आप आसानी से देख सकें. यह जांचें कि 3 का मतलब है कि 1+1 के बराबर है.

  1. assertEquals(3, 1 + 1) को addition_isCorrect टेस्ट में जोड़ें.

ExampleUnitTest.kt

class ExampleUnitTest {

   // Each test is annotated with @Test (this is a Junit annotation)
   @Test
   fun addition_isCorrect() {
       assertEquals(4, 2 + 2)
       assertEquals(3, 1 + 1) // This should fail
   }
}
  1. जांच करना.
  1. जांच के नतीजों में, जांच के आगे X देखें.

  1. यह भी ध्यान रखें:
  • किसी एक दावे पर कार्रवाई न हो पाने की वजह से उसकी जांच नहीं की जा सकती.
  • आपको अनुमानित वैल्यू (3) बनाम उस वैल्यू के बारे में बताया जाता है जो असल में कैलकुलेट की गई थी (2).
  • आपको विफल दावे (ExampleUnitTest.kt:16) की लाइन पर भेजा जाता है.

तीसरा चरण: इंस्ट्रूमेंटल टेस्ट चलाना

इंस्ट्रुमेंटेड टेस्ट, androidTest सोर्स सेट में हैं.

  1. androidTest स्रोत सेट खोलें.
  2. ExampleInstrumentedTest नाम की जांच करें.

उदाहरण के तौर पर इस्तेमाल किया गया टेस्ट

@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
    @Test
    fun useAppContext() {
        // Context of the app under test.
        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
        assertEquals("com.example.android.architecture.blueprints.reactive",
            appContext.packageName)
    }
}

स्थानीय टेस्ट के उलट, यह टेस्ट डिवाइस पर चलता है (उदाहरण के तौर पर, एम्युलेट किए गए Pixel 2 फ़ोन के नीचे दिया गया उदाहरण):

अगर आपके पास कोई डिवाइस या एम्युलेटर चल रहा है, तो आपको एम्युलेटर पर टेस्ट चल रहा है.

इस टास्क में, आप getActiveAndCompleteStats के लिए टेस्ट लिखेंगे, जो आपके ऐप्लिकेशन के लिए चालू और पूरे हो चुके टास्क के आंकड़ों के प्रतिशत का हिसाब लगाता है. आप इन आंकड़ों को ऐप्लिकेशन की आंकड़ों की स्क्रीन पर देख सकते हैं.

चरण 1: टेस्ट क्लास बनाना

  1. main सोर्स सेट में, todoapp.statistics के अंदर StatisticsUtils.kt खोलें.
  2. getActiveAndCompletedStats फ़ंक्शन ढूंढें.

आंकड़ेUtils.kt

internal fun getActiveAndCompletedStats(tasks: List<Task>?): StatsResult {

   val totalTasks = tasks!!.size
   val numberOfActiveTasks = tasks.count { it.isActive }
   val activePercent = 100 * numberOfActiveTasks / totalTasks
   val completePercent = 100 * (totalTasks - numberOfActiveTasks) / totalTasks

   return StatsResult(
       activeTasksPercent = activePercent.toFloat(),
       completedTasksPercent = completePercent.toFloat()
   )
  
}

data class StatsResult(val activeTasksPercent: Float, val completedTasksPercent: Float)

getActiveAndCompletedStats फ़ंक्शन, टास्क की सूची को स्वीकार करता है और StatsResult दिखाता है. StatsResult एक डेटा क्लास है, जिसमें दो संख्याएं होती हैं. यह टास्क पूरे होते हैं, और प्रतिशत के तौर पर चालू है.

Android Studio में आपको ऐसे टूल मिलते हैं जो टेस्ट स्टब जनरेट करते हैं. इससे आपको इस फ़ंक्शन के लिए टेस्ट लागू करने में मदद मिलती है.

  1. दायां क्लिक करेंgetActiveAndCompletedStats और Generate > Test चुनें.

टेस्ट बनाएं डायलॉग खुलता है:

  1. क्लास के नाम: को StatisticsUtilsTest में बदलें (StatisticsUtilsKtTest के बजाय; यह यूआरएल #39 होता है, जो कि टेस्ट क्लास के नाम में KT नहीं होता).
  2. बाकी डिफ़ॉल्ट सेटिंग रखें. JUnit 4 टेस्ट करने के लिए सही लाइब्रेरी है. डेस्टिनेशन पैकेज सही है (यह StatisticsUtils क्लास की जगह की जानकारी देता है) और आपको किसी एक चेक बॉक्स में सही का निशान लगाने की ज़रूरत नहीं है. ये सिर्फ़ अतिरिक्त कोड जनरेट करते हैं. हालांकि, आप अपना टेस्ट बिल्कुल शुरू से लिखेंगे.
  3. ठीक है दबाएं

डिलीवरी की डायरेक्ट्री चुनें डायलॉग खुलता है:

आप #स्थानीय टेस्ट कर रहे हैं, क्योंकि आपके फ़ंक्शन के ज़रिए गणित का हिसाब लगाया जा रहा है और इसमें कोई Android कोड शामिल नहीं किया जाएगा. इसलिए, इसे किसी असली या एम्युलेट किए गए डिवाइस पर चलाने की ज़रूरत नहीं है.

  1. test डायरेक्ट्री (न कि androidTest) चुनें, क्योंकि आप स्थानीय टेस्ट लिख रहे हैं.
  2. ठीक है पर क्लिक करें.
  3. ध्यान दें कि test/statistics/ में StatisticsUtilsTest क्लास जनरेट की गई.

दूसरा चरण: जांच के लिए अपना पहला फ़ंक्शन लिखना

आप एक जांच लिखने वाले हैं, जो:

  • अगर कोई पूरा हो चुका टास्क न हो और एक चालू टास्क हो,
  • चालू जांच का प्रतिशत 100% है,
  • और पूरे हो चुके टास्क का प्रतिशत 0% है.
  1. StatisticsUtilsTest खोलें.
  2. getActiveAndCompletedStats_noCompleted_returnsHundredZero नाम का फ़ंक्शन बनाएं.

आंकड़ेUtilsTest.kt

class StatisticsUtilsTest {

    fun getActiveAndCompletedStats_noCompleted_returnsHundredZero() {
        // Create an active task

        // Call your function

        // Check the result
    }
}
  1. टेस्ट का संकेत देने के लिए, फ़ंक्शन के नाम के ऊपर @Test एनोटेशन जोड़ें. यह टेस्ट ##39 होता है.
  2. टास्क की सूची बनाएं.
// Create an active task 
val tasks = listOf<Task>(
            Task("title", "desc", isCompleted = false)
        )
  1. इन टास्क के साथ, getActiveAndCompletedStats पर कॉल करें.
// Call your function
val result = getActiveAndCompletedStats(tasks)
  1. दावों का इस्तेमाल करके, देखें कि result आपके हिसाब से है या नहीं.
// Check the result
assertEquals(result.completedTasksPercent, 0f)
assertEquals(result.activeTasksPercent, 100f)

यह रहा पूरा कोड.

आंकड़ेUtilsTest.kt

class StatisticsUtilsTest {

    @Test
    fun getActiveAndCompletedStats_noCompleted_returnsHundredZero() {

        // Create an active task (the false makes this active)
        val tasks = listOf<Task>(
            Task("title", "desc", isCompleted = false)
        )
        // Call your function
        val result = getActiveAndCompletedStats(tasks)

        // Check the result
        assertEquals(result.completedTasksPercent, 0f)
        assertEquals(result.activeTasksPercent, 100f)
    }
}
  1. टेस्ट चलाएं (StatisticsUtilsTest पर क्लिक करें और चलाएं).

इसे पास होना चाहिए:

तीसरा चरण: Hamcrest डिपेंडेंसी जोड़ना

आपका टेस्ट, आपके कोड के काम करने के दस्तावेज़ के तौर पर काम करता है. इसलिए, लोग इन्हें आसानी से पढ़ सकते हैं. इन दो दावों की तुलना करें:

assertEquals(result.completedTasksPercent, 0f)

// versus

assertThat(result.completedTasksPercent, `is`(0f))

दूसरा दावा, इंसान के वाक्य की तरह दिखता है. इसे Hamcrest नाम के दावे वाले फ़्रेमवर्क का इस्तेमाल करके लिखा गया है. पढ़ने लायक दावे लिखने का एक और अच्छा टूल ट्रूथ लाइब्रेरी है. आप इस कोडलैब में हैमक्रेस्ट का इस्तेमाल करके, दावे दर्ज करेंगे.

  1. build.grade (Module: app) खोलें और यह डिपेंडेंसी जोड़ें.

app/build.gradle

dependencies {
    // Other dependencies
    testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"
}

आम तौर पर, डिपेंडेंसी जोड़ते समय implementation का इस्तेमाल किया जाता है. हालांकि, यहां आपtestImplementation का इस्तेमाल कर रहे हैं. जब आप #39;अपने ऐप्लिकेशन को दुनिया के साथ शेयर करने के लिए तैयार हों, तब बेहतर होगा कि आप अपने ऐप्लिकेशन के किसी भी टेस्ट कोड या डिपेंडेंसी के साथ अपने APK का साइज़ न बढ़ाएं. आप gradle कॉन्फ़िगरेशन का इस्तेमाल करके, यह तय कर सकते हैं कि लाइब्रेरी को मुख्य या टेस्ट कोड में शामिल किया जाना चाहिए या नहीं. सबसे सामान्य कॉन्फ़िगरेशन ये हैं:

  • implementation—डिपेंडेंसी, सभी सोर्स सेट में उपलब्ध है. इनमें टेस्ट सोर्स सेट भी शामिल हैं.
  • testImplementation— डिपेंडेंसी सिर्फ़ टेस्ट सोर्स सेट में उपलब्ध है.
  • androidTestImplementation— डिपेंडेंसी सिर्फ़ androidTest सोर्स सेट में उपलब्ध है.

आप कौनसा कॉन्फ़िगरेशन इस्तेमाल करते हैं, यह तय करता है कि डिपेंडेंसी कहां इस्तेमाल की जा सकती है. अगर आप:

testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"

इसका मतलब है कि हैमक्रेस्ट सिर्फ़ टेस्ट सोर्स सेट में उपलब्ध होगा. इससे यह भी पक्का होता है कि Hamcrest को आपके फ़ाइनल ऐप्लिकेशन में शामिल नहीं किया जाएगा.

चौथा चरण: दावे लिखने के लिए, Hamcrest का इस्तेमाल करें

  1. assertEquals के बजाय Hamcrest's assertThat का इस्तेमाल करने के लिए, getActiveAndCompletedStats_noCompleted_returnsHundredZero() टेस्ट को अपडेट करें.
// REPLACE
assertEquals(result.completedTasksPercent, 0f)
assertEquals(result.activeTasksPercent, 100f)

// WITH
assertThat(result.activeTasksPercent, `is`(100f))
assertThat(result.completedTasksPercent, `is`(0f))

ध्यान दें कि इंपोर्ट किए जाने पर, आप इंपोर्ट import org.hamcrest.Matchers.`is` का इस्तेमाल कर सकते हैं.

फ़ाइनल टेस्ट नीचे दिए गए कोड जैसा दिखेगा.

आंकड़ेUtilsTest.kt

import com.example.android.architecture.blueprints.todoapp.data.Task
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.`is`
import org.junit.Test

class StatisticsUtilsTest {

    @Test
    fun getActiveAndCompletedStats_noCompleted_returnsHundredZero {

        // Create an active tasks (the false makes this active)
        val tasks = listOf<Task>(
            Task("title", "desc", isCompleted = false)
        )
        // Call your function
        val result = getActiveAndCompletedStats(tasks)

        // Check the result
        assertThat(result.activeTasksPercent, `is`(100f))
        assertThat(result.completedTasksPercent, `is`(0f))

    }
}
  1. अपडेट किया गया टेस्ट चलाएं, ताकि यह पक्का हो सके कि यह अब भी काम कर रहा है!

यह कोडलैब आपको हैम ऊंचाई की पूरी जानकारी नहीं देएगा. इसलिए, अगर आप #39;ज़्यादा जानना चाहते हैं, तो आधिकारिक ट्यूटोरियल देखें.

यह प्रैक्टिस के लिए, वैकल्पिक टास्क है.

इस टास्क में, आप JUnit और Hamcrest का इस्तेमाल करके ज़्यादा टेस्ट लिखेंगे. आप भी टेस्ट ड्राइव डेवलपमेंट प्रोग्राम की रणनीति का इस्तेमाल करके, टेस्ट लिखेंगे. टेस्ट ड्रिवन डेवलपमेंट या टीडीडी, प्रोग्रामिंग का एक स्कूल है, जिसमें आपका फ़ीचर कोड लिखने के बजाय सबसे पहले टेस्ट लिखने की बात कही जाती है. फिर आप अपना टेस्ट कोड पास करने के लक्ष्य के साथ अपना फ़ीचर कोड लिखते हैं.

पहला चरण. टेस्ट लिखना

जब आपके पास सामान्य टास्क की सूची हो, तब जांच लिखें:

  1. अगर एक पूरा हो चुका कोई टास्क नहीं है, तो activeTasks टास्क 0f होना चाहिए, और पूरे हो चुके टास्क का प्रतिशत 100f होना चाहिए .
  2. अगर पूरे हो चुके दो टास्क और तीन चालू टास्क हैं, तो पूरा हो चुका प्रतिशत 40f होना चाहिए और सक्रिय प्रतिशत 60f होना चाहिए.

दूसरा चरण. गड़बड़ी की जांच करना

getActiveAndCompletedStats के कोड में एक गड़बड़ी है. ध्यान दें कि यह कैसे तय करता है कि सूची खाली है या शून्य है. इन दोनों मामलों में, दोनों प्रतिशत शून्य होने चाहिए.

internal fun getActiveAndCompletedStats(tasks: List<Task>?): StatsResult {

   val totalTasks = tasks!!.size
   val numberOfActiveTasks = tasks.count { it.isActive }
   val activePercent = 100 * numberOfActiveTasks / totalTasks
   val completePercent = 100 * (totalTasks - numberOfActiveTasks) / totalTasks

   return StatsResult(
       activeTasksPercent = activePercent.toFloat(),
       completedTasksPercent = completePercent.toFloat()
   )
  
}

कोड ठीक करने और जांच लिखने के लिए, आप #35; टेस्ट-ड्रिवन डेवलपमेंट का इस्तेमाल करेंगे. टेस्ट पर आधारित डेवलपमेंट इन चरणों के मुताबिक होना चाहिए.

  1. दिया गया, कब, फिर स्ट्रक्चर का इस्तेमाल करके, टेस्ट करें और नाम को फ़ॉलो करने वाले नाम से लिखें.
  2. टेस्ट फ़ेल हो जाने की पुष्टि करें.
  3. टेस्ट पास करने के लिए कम से कम कोड लिखें.
  4. सभी टेस्ट के लिए दोहराएं!

गड़बड़ी को ठीक करने के बजाय, टेस्ट सबसे पहले लिखें. इसके बाद, आप इस बात की पुष्टि कर सकते हैं कि आने वाले समय में कभी भी गलती से दोबारा आने वाले टेस्ट से आपको सुरक्षा मिल सके.

  1. अगर कोई खाली सूची emptyList() है, तो दोनों प्रतिशत 0f होना चाहिए.
  2. अगर टास्क लोड करने में कोई गड़बड़ी हुई, तो सूची null होगी और दोनों प्रतिशत 0f होने चाहिए.
  3. अपने टेस्ट चलाएं और पुष्टि करें कि वे काम नहीं करते:

तीसरा चरण. गड़बड़ी ठीक करें

अब अपनी जांच के लिए, गड़बड़ी ठीक करें.

  1. अगर tasks null या खाली है, तो 0f में वापस जाकर getActiveAndCompletedStats में गड़बड़ी को ठीक करें:
internal fun getActiveAndCompletedStats(tasks: List<Task>?): StatsResult {

    return if (tasks == null || tasks.isEmpty()) {
        StatsResult(0f, 0f)
    } else {
        val totalTasks = tasks.size
        val numberOfActiveTasks = tasks.count { it.isActive }
        StatsResult(
            activeTasksPercent = 100f * numberOfActiveTasks / tasks.size,
            completedTasksPercent = 100f * (totalTasks - numberOfActiveTasks) / tasks.size
        )
    }
}
  1. अपने टेस्ट फिर से चलाएं और पुष्टि करें कि अब सभी टेस्ट पास हो गए हैं!

TDD को फ़ॉलो करने और पहले टेस्ट लिखने से, आपने यह पक्का कर लिया है कि:

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

समाधान: ज़्यादा टेस्ट लिखना

यहां सभी टेस्ट और उनसे जुड़े फ़ीचर कोड के बारे में बताया गया है.

आंकड़ेUtilsTest.kt

class StatisticsUtilsTest {

    @Test
    fun getActiveAndCompletedStats_noCompleted_returnsHundredZero {
        val tasks = listOf(
            Task("title", "desc", isCompleted = false)
        )
        // When the list of tasks is computed with an active task
        val result = getActiveAndCompletedStats(tasks)

        // Then the percentages are 100 and 0
        assertThat(result.activeTasksPercent, `is`(100f))
        assertThat(result.completedTasksPercent, `is`(0f))
    }

    @Test
    fun getActiveAndCompletedStats_noActive_returnsZeroHundred() {
        val tasks = listOf(
            Task("title", "desc", isCompleted = true)
        )
        // When the list of tasks is computed with a completed task
        val result = getActiveAndCompletedStats(tasks)

        // Then the percentages are 0 and 100
        assertThat(result.activeTasksPercent, `is`(0f))
        assertThat(result.completedTasksPercent, `is`(100f))
    }

    @Test
    fun getActiveAndCompletedStats_both_returnsFortySixty() {
        // Given 3 completed tasks and 2 active tasks
        val tasks = listOf(
            Task("title", "desc", isCompleted = true),
            Task("title", "desc", isCompleted = true),
            Task("title", "desc", isCompleted = true),
            Task("title", "desc", isCompleted = false),
            Task("title", "desc", isCompleted = false)
        )
        // When the list of tasks is computed
        val result = getActiveAndCompletedStats(tasks)

        // Then the result is 40-60
        assertThat(result.activeTasksPercent, `is`(40f))
        assertThat(result.completedTasksPercent, `is`(60f))
    }

    @Test
    fun getActiveAndCompletedStats_error_returnsZeros() {
        // When there's an error loading stats
        val result = getActiveAndCompletedStats(null)

        // Both active and completed tasks are 0
        assertThat(result.activeTasksPercent, `is`(0f))
        assertThat(result.completedTasksPercent, `is`(0f))
    }

    @Test
    fun getActiveAndCompletedStats_empty_returnsZeros() {
        // When there are no tasks
        val result = getActiveAndCompletedStats(emptyList())

        // Both active and completed tasks are 0
        assertThat(result.activeTasksPercent, `is`(0f))
        assertThat(result.completedTasksPercent, `is`(0f))
    }
}

आंकड़ेUtils.kt

internal fun getActiveAndCompletedStats(tasks: List<Task>?): StatsResult {

    return if (tasks == null || tasks.isEmpty()) {
        StatsResult(0f, 0f)
    } else {
        val totalTasks = tasks.size
        val numberOfActiveTasks = tasks.count { it.isActive }
        StatsResult(
            activeTasksPercent = 100f * numberOfActiveTasks / tasks.size,
            completedTasksPercent = 100f * (totalTasks - numberOfActiveTasks) / tasks.size
        )
    }
}

आपने लिखने और दौड़ने से जुड़ी बुनियादी बातें जान ली हैं! अब आप #39; बुनियादी ViewModel और LiveData टेस्ट लिखने का तरीका जानेंगे.

बाकी कोडलैब (कोड बनाना सीखना) में, आप दो # Android क्लास के लिए टेस्ट लिखने का तरीका जानेंगे जो आम तौर पर ज़्यादातर ऐप्लिकेशन में काम करती हैं—ViewModel और LiveData.

आप TasksViewModel के लिए टेस्ट लिखना शुरू करेंगे.


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



आप जिस जांच में #&93 करेंगे; वह जांच करेगा कि जब आप addNewTask वाले तरीके से कॉल करेंगे, तो नई टास्क विंडो को खोलने के लिए Event को सक्रिय किया जाएगा. यह ऐप्लिकेशन कोड आपकी जांच के लिए है.

TasksViewModel.kt

fun addNewTask() {
   _newTaskEvent.value = Event(Unit)
}

पहला चरण. TasksViewModelTest क्लास बनाना

StatisticsUtilTest के लिए आपने जो तरीका अपनाया है उसी का इस्तेमाल करके, इस चरण में TasksViewModelTest के लिए कोई टेस्ट फ़ाइल बनाएं.

  1. आप जिस कक्षा की जांच करना चाहते हैं उसे tasks पैकेज, TasksViewModel. में खोलें
  2. कोड में, क्लास के नाम पर दायां क्लिक करें TasksViewModel -> जनरेट करें -> जांच करें.

  1. टेस्ट बनाएं स्क्रीन पर, स्वीकार करने के लिए ठीक है पर क्लिक करें (कोई भी डिफ़ॉल्ट सेटिंग बदलने की ज़रूरत नहीं).
  2. डेस्टिनेशन डायरेक्ट्री चुनें डायलॉग पर, जांच डायरेक्ट्री चुनें.

दूसरा चरण. अपना ViewModel टेस्ट लिखना शुरू करें

इस कदम में आप व्यू व्यू मॉडल की जांच करते हैं. इससे यह पता चलता है कि addNewTask तरीके को कॉल करने पर, नए टास्क विंडो को खोलने के लिए Event चालू हो जाता है.

  1. addNewTask_setsNewTaskEvent नाम की नई जांच बनाएं.

TasksViewModelTest.kt

class TasksViewModelTest {

    @Test
    fun addNewTask_setsNewTaskEvent() {

        // Given a fresh TasksViewModel


        // When adding a new task


        // Then the new task event is triggered

    }
    
}

आवेदन का संदर्भ क्या है?

जब आप टेस्ट करने के लिए TasksViewModel का इंस्टेंस बनाते हैं, तो इसके कंस्ट्रक्टर को ऐप्लिकेशन कॉन्टेक्स्ट की ज़रूरत होती है. हालांकि, इस टेस्ट में आप गतिविधियों और यूज़र इंटरफ़ेस (यूआई) और फ़्रैगमेंट का इस्तेमाल करके पूरा ऐप्लिकेशन नहीं बना रहे हैं. ऐसे में, आपको ऐप्लिकेशन के बारे में जानकारी कैसे मिलेगी?

TasksViewModelTest.kt

// Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(???)

AndroidX टेस्ट लाइब्रेरी में ऐसी क्लास और मेथड शामिल हैं जो आपको जांच के मकसद से बनाए गए ऐप्लिकेशन और ऐक्टिविटी जैसे कॉम्पोनेंट के वर्शन उपलब्ध कराते हैं. जब आपके पास स्थानीय टेस्ट होता है, जहां आपको सिम्युलेटेड Android फ़्रेमवर्क क्लास(जैसे कि ऐप्लिकेशन कॉन्टेक्स्ट) की ज़रूरत होती है, तब AndroidX टेस्ट सही तरीके से सेट अप करने के लिए यह तरीका अपनाएं:

  1. AndroidX टेस्ट को मुख्य और एक्सपेंडेंसी जोड़ें
  2. Robolectric टेस्टिंग लाइब्रेरी निर्भरता जोड़ें
  3. AndroidJunit4 टेस्ट रनर से क्लास को एनोटेट करना
  4. AndroidX टेस्ट कोड लिखें

आप ये चरण पूरे करने वाले हैं और फिर आप दोनों के मिलकर काम करने के तरीके को समझ जाएंगे.

तीसरा चरण. Gradle डिपेंडेंसी जोड़ना

  1. इन Android ऐप्लिकेशन मॉड्यूल की build.gradle फ़ाइल में इन डिपेंडेंसी को कॉपी करें. इससे, Android Auto की मुख्य कोर और एक्सपेंडेंसी के साथ-साथ Robolectric टेस्टिंग डिपेंडेंसी जोड़ी जा सकेगी.

app/build.gradle

    // AndroidX Test - JVM testing
testImplementation "androidx.test.ext:junit-ktx:$androidXTestExtKotlinRunnerVersion"

    testImplementation "androidx.test:core-ktx:$androidXTestCoreVersion"

 testImplementation "org.robolectric:robolectric:$robolectricVersion"

चरण 4. JUnit टेस्ट रनर जोड़ें

  1. @RunWith(AndroidJUnit4::class) को अपनी टेस्ट क्लास के ऊपर जोड़ें.

TasksViewModelTest.kt

@RunWith(AndroidJUnit4::class)
class TasksViewModelTest {
    // Test code
}

चरण 5. AndroidX टेस्ट का इस्तेमाल करना

अब आप AndroidX टेस्ट लाइब्रेरी का इस्तेमाल कर सकते हैं. इसमें ऐसा तरीका ApplicationProvider.getApplicationContext शामिल है जिसमें ऐप्लिकेशन के बारे में जानकारी दी जाती है.

  1. AndroidX टेस्ट लाइब्रेरी से ApplicationProvider.getApplicationContext() का इस्तेमाल करके TasksViewModel बनाएं.

TasksViewModelTest.kt

// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
  1. addNewTask को tasksViewModel पर कॉल करें.

TasksViewModelTest.kt

tasksViewModel.addNewTask()

इस समय आपका टेस्ट नीचे दिए गए कोड जैसा दिखना चाहिए.

TasksViewModelTest.kt

    @Test
    fun addNewTask_setsNewTaskEvent() {

        // Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

        // When adding a new task
        tasksViewModel.addNewTask()

        // Then the new task event is triggered
        // TODO test LiveData
    }
  1. पुष्टि करें कि यह काम करता है या नहीं, इसकी जांच करने के लिए चलाएं.

कॉन्सेप्ट: AndroidX टेस्ट कैसे काम करता है?

AndroidX टेस्ट क्या है?

AndroidX टेस्ट, जांच के लिए लाइब्रेरी का एक संग्रह है. इसमें क्लास और मेथड शामिल हैं. ये आपको ऐप्लिकेशन और ऐक्टिविटी जैसे कॉम्पोनेंट के वर्शन देते हैं, जिनका इस्तेमाल जांच के मकसद से किया जाता है. उदाहरण के लिए, आपने जो कोड लिखा है वह ऐप्लिकेशन कॉन्टेक्स्ट पाने के लिए AndroidX टेस्ट फ़ंक्शन का उदाहरण है.

ApplicationProvider.getApplicationContext()

AndroidX Test API का एक फ़ायदा यह भी है कि इसे स्थानीय जांचों और इंस्ट्रूमेंट किए गए परीक्षण, दोनों के लिए काम करने के लिए बनाया गया है. यह अच्छा है, क्योंकि:

  • आप स्थानीय जांच या इंस्ट्रूमेंटेड टेस्ट की तरह ही टेस्ट कर सकते हैं.
  • आपको स्थानीय बनाम इंस्ट्रूमेंटल टेस्टिंग के लिए, अलग-अलग टेस्टिंग एपीआई जानने की ज़रूरत नहीं है.

उदाहरण के लिए, आपने AndroidX टेस्ट लाइब्रेरी का इस्तेमाल करके कोड लिखा है. इसलिए, आप TasksViewModelTest फ़ोल्डर को test फ़ोल्डर से androidTest फ़ोल्डर में ले जा सकते हैं. इससे, जांच अब भी होगी. getApplicationContext() अलग-अलग तरीके से काम करता है. यह इस बात पर निर्भर करता है कि इसे स्थानीय या इंस्ट्रूमेंट के तौर पर चलाया जा रहा है या नहीं:

  • अगर यह इंस्ट्रूमेंट किया गया टेस्ट है, तो इसे एम्युलेटर चालू करने या किसी असली डिवाइस से कनेक्ट होने पर ऐप्लिकेशन का असल कॉन्टेक्स्ट मिलेगा.
  • अगर इसमें स्थानीय टेस्ट है, तो यह सिम्युलेट किए गए Android एनवायरमेंट का इस्तेमाल करता है.

रोबोलेट्रिक क्या है?

AndroidX टेस्ट, स्थानीय टेस्ट के लिए जिस Android एनवायरमेंट का इस्तेमाल करता है वह Robolectric ने उपलब्ध कराया है. Robolectric एक लाइब्रेरी है जो जांच के लिए सिम्युलेट किया गया Android एनवायरमेंट बनाती है. साथ ही, यह एम्युलेटर को चालू करने या डिवाइस पर तेज़ी से चलाने से ज़्यादा तेज़ काम करती है. Robolectic डिपेंडेंसी के बिना, आपको यह गड़बड़ी मिलेगी:

@RunWith(AndroidJUnit4::class)क्या करता है?

टेस्ट रनर एक JUnit कॉम्पोनेंट है जो टेस्ट चलाता है. टेस्ट रनर के बिना, आपकी जांच चालू नहीं होगी. यह डिफ़ॉल्ट रूप से JUnit की ओर से उपलब्ध कराया गया एक रनर है, जो आपको अपने-आप मिल जाता है. @RunWith यह डिफ़ॉल्ट रनर रन करता है.

AndroidJUnit4 टेस्ट रनर की मदद से, AndroidX टेस्ट अलग-अलग तरीके से टेस्ट किया जा सकता है. यह इस बात पर निर्भर करता है कि टेस्ट को इंस्ट्रुमेंट किया गया है या स्थानीय टेस्ट.

चरण 6. रोबोलेट्रिक चेतावनी ठीक करना

कोड चलाते समय, ध्यान दें कि Robolectric का इस्तेमाल किया जाता है.

AndroidX टेस्ट और AndroidJunit4 टेस्ट रनर की वजह से, आपके बिना सीधे Roboectric कोड की एक लाइन लिखे बिना ही ऐसा होता है!

आपको दो चेतावनियां दिख सकती हैं.

  • No such manifest file: ./AndroidManifest.xml
  • "WARN: Android SDK 29 requires Java 9..."

आप अपनी Gradle फ़ाइल को अपडेट करके, No such manifest file: ./AndroidManifest.xml चेतावनी को ठीक कर सकते हैं.

  1. अपनी Gradle फ़ाइल में नीचे दी गई लाइन जोड़ें, ताकि Android के सही मेनिफ़ेस्ट का इस्तेमाल किया जा सके. includeAndroidResources विकल्प की मदद से, आप अपनी यूनिट टेस्ट में Android रिसॉर्स ऐक्सेस कर सकते हैं. इनमें, आपकी AndroidManifest फ़ाइल भी शामिल है.

app/build.gradle

    // Always show the result of every unit test when running via command line, even if it passes.
    testOptions.unitTests {
        includeAndroidResources = true

        // ... 
    }

चेतावनी "WARN: Android SDK 29 requires Java 9..." ज़्यादा जटिल है. Android Q पर टेस्टिंग के लिए, Java 9 की ज़रूरत होती है. Java Studio 9 का इस्तेमाल करने के लिए, Android Studio को इस कोडलैब के लिए कॉन्फ़िगर करने की जगह, टारगेट को 28 पर सेट करें.

खास जानकारी:

  • आम तौर पर, प्योर व्यू मॉडल की जांच test सोर्स सेट में की जा सकती है, क्योंकि उनके कोड के लिए आम तौर पर Android की ज़रूरत नहीं होती.
  • ऐप्लिकेशन और गतिविधियों जैसे कॉम्पोनेंट के टेस्ट वर्शन पाने के लिए, AndroidX टेस्टलाइब्रेरी का इस्तेमाल किया जा सकता है.
  • अगर आपको अपने test सोर्स सेट में सिम्युलेट किया गया Android कोड चलाना है, तो आप Robolectric डिपेंडेंसी और @RunWith(AndroidJUnit4::class) एनोटेशन जोड़ सकते हैं.

बधाई हो, आप टेस्ट करने के लिए AndroidX टेस्टिंग लाइब्रेरी और Robolectric, दोनों का इस्तेमाल कर रहे हैं. आपकी जांच पूरी नहीं हुई है (आपने अभी तक #19 में कोई दावा नहीं लिखा है, यह अभी और कहा जा सकता है).// TODO test LiveData).{0}'आगे आपको LiveData के साथ दावा करने की जानकारी मिलेगी.

इस टास्क में, आप #33; LiveData वैल्यू पर सही तरीके से दावा करने का तरीका जानेंगे.

आपने यहां addNewTask_setsNewTaskEvent व्यू मॉडल टेस्ट के बिना छोड़ा है.

TasksViewModelTest.kt

    @Test
    fun addNewTask_setsNewTaskEvent() {

        // Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

        // When adding a new task
        tasksViewModel.addNewTask()

        // Then the new task event is triggered
        // TODO test LiveData
    }
    

LiveData को टेस्ट करने के लिए दो तरीकों का सुझाव दिया जाता है:

  1. InstantTaskExecutorRule का इस्तेमाल करें
  2. पक्का करें कि LiveData निगरानी

पहला चरण. InstantTaskExecutorRule इस्तेमाल करें

InstantTaskExecutorRule JUnit का नियम है. जब आप @get:Rule एनोटेशन के साथ इसका इस्तेमाल करते हैं, तो InstantTaskExecutorRule क्लास में कुछ कोड, जांच से पहले और बाद में चलते हैं. (असल कोड देखने के लिए, कीबोर्ड शॉर्टकट Command+B का इस्तेमाल करके फ़ाइल देखी जा सकती है).

यह नियम एक ही थ्रेड में, आर्किटेक्चर कॉम्पोनेंट से जुड़े सभी बैकग्राउंड जॉब चलाता है, ताकि टेस्ट के नतीजे सिंक होते रहें और उन्हें दोहराया जा सके. जब आप लाइव डेटा की जांच वाले टेस्ट लिखते हैं, तो इस नियम का इस्तेमाल करें!

  1. आर्किटेक्चर कॉम्पोनेंट कॉम्पोनेंट कोर टेस्टिंग लाइब्रेरी (जिसमें यह नियम शामिल है) के लिए, ग्रेडल डिपेंडेंसी जोड़ें.

app/build.gradle

testImplementation "androidx.arch.core:core-testing:$archTestingVersion"
  1. TasksViewModelTest.kt खोलें
  2. TasksViewModelTest क्लास में InstantTaskExecutorRule जोड़ें.

TasksViewModelTest.kt

class TasksViewModelTest {
    @get:Rule
    var instantExecutorRule = InstantTaskExecutorRule()
    
    // Other code...
}

दूसरा चरण. LiveDataTestUtil.kt क्लास जोड़ें

आपका अगला कदम यह पक्का करना है कि LiveData और #39;टेस्ट जांच का पालन किया जा रहा है.

जब आप LiveData का इस्तेमाल करते हैं, तो आम तौर पर आपके पास कोई गतिविधि या फ़्रैगमेंट (LifecycleOwner) होता है, जो LiveData की निगरानी करता है.

viewModel.resultLiveData.observe(fragment, Observer {
    // Observer code here
})

यह निगरानी ज़रूरी है. LiveData के लिए, आपको मौजूदा ऑब्ज़र्वर की ज़रूरत होगी

  • किसी भी onChanged इवेंट को ट्रिगर करे.
  • कोई भी बदलाव ट्रिगर करें.

अपने व्यू मॉडल LiveData का LiveData व्यवहार तय करने के लिए, आपको LiveData LifecycleOwner का इस्तेमाल करना होगा.

इससे कोई समस्या होती है: आपके TasksViewModel टेस्ट में, आपके LiveData की निगरानी करने के लिए, कोई गतिविधि या फ़्रैगमेंट नहीं है. इसके बारे में जानने के लिए, observeForever वाला तरीका इस्तेमाल करें. इससे यह पक्का किया जाता है कि बिना LifecycleOwner के, LiveData को लगातार देखा जा रहा है. जब आप observeForever करते हैं, तो आपको ऑब्ज़र्वर को हटाना याद रखना या ऑब्ज़र्वर लीक का जोखिम रखना होगा.

यह नीचे दिए गए कोड जैसा दिखता है. इसकी जांच करें:

@Test
fun addNewTask_setsNewTaskEvent() {

    // Given a fresh ViewModel
    val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())


    // Create observer - no need for it to do anything!
    val observer = Observer<Event<Unit>> {}
    try {

        // Observe the LiveData forever
        tasksViewModel.newTaskEvent.observeForever(observer)

        // When adding a new task
        tasksViewModel.addNewTask()

        // Then the new task event is triggered
        val value = tasksViewModel.newTaskEvent.value
        assertThat(value?.getContentIfNotHandled(), (not(nullValue())))

    } finally {
        // Whatever happens, don't forget to remove the observer!
        tasksViewModel.newTaskEvent.removeObserver(observer)
    }
}

यह टेस्ट के तौर पर एक LiveData की जांच करने के लिए, कई बॉयलरप्लेट कोड का इस्तेमाल करता है! इस बॉयलरप्लेट से छुटकारा पाने के कुछ तरीके हैं. आप #39;LiveDataTestUtil नाम का एक एक्सटेंशन फ़ंक्शन बनाने वाले हैं, ताकि ऑब्ज़र्वर जोड़ना आसान हो सके.

  1. अपने test सोर्स सेट में, LiveDataTestUtil.kt नाम की एक नई Kotlin फ़ाइल बनाएं.


  1. कोड को कॉपी करके नीचे चिपकाएं.

LiveDataTestUtil.kt

import androidx.annotation.VisibleForTesting
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException


@VisibleForTesting(otherwise = VisibleForTesting.NONE)
fun <T> LiveData<T>.getOrAwaitValue(
    time: Long = 2,
    timeUnit: TimeUnit = TimeUnit.SECONDS,
    afterObserve: () -> Unit = {}
): T {
    var data: T? = null
    val latch = CountDownLatch(1)
    val observer = object : Observer<T> {
        override fun onChanged(o: T?) {
            data = o
            latch.countDown()
            this@getOrAwaitValue.removeObserver(this)
        }
    }
    this.observeForever(observer)

    try {
        afterObserve.invoke()

        // Don't wait indefinitely if the LiveData is not set.
        if (!latch.await(time, timeUnit)) {
            throw TimeoutException("LiveData value was never set.")
        }

    } finally {
        this.removeObserver(observer)
    }

    @Suppress("UNCHECKED_CAST")
    return data as T
}

यह काफ़ी जटिल तरीका है. यह getOrAwaitValue नाम का एक Kotlin एक्सटेंशन फ़ंक्शन बनाता है जो ऑब्ज़र्वर जोड़ता है, LiveData वैल्यू पाता है, और फिर ऑब्ज़र्वर को साफ़ करता है—आम तौर पर, ऊपर दिखाए गए observeForever कोड का छोटा और फिर से इस्तेमाल किया जा सकने वाला वर्शन. इस क्लास की पूरी जानकारी के लिए, यह ब्लॉग पोस्ट देखें.

तीसरा चरण. दावा लिखने के लिए getOrAWaittValue का इस्तेमाल करना

इस चरण में, getOrAwaitValue तरीके का इस्तेमाल करें और एक ऐसा स्टेटमेंट बनाएं जो यह जांच करे कि newTaskEvent ट्रिगर हुआ था.

  1. getOrAwaitValue का इस्तेमाल करके newTaskEvent के लिए LiveData वैल्यू पाएं.
val value = tasksViewModel.newTaskEvent.getOrAwaitValue()
  1. दावा करें कि वैल्यू शून्य नहीं है.
assertThat(value.getContentIfNotHandled(), (not(nullValue())))

पूरा टेस्ट नीचे दिए गए कोड जैसा दिखना चाहिए.

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.example.android.architecture.blueprints.todoapp.getOrAwaitValue
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.not
import org.hamcrest.Matchers.nullValue
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class TasksViewModelTest {

    @get:Rule
    var instantExecutorRule = InstantTaskExecutorRule()


    @Test
    fun addNewTask_setsNewTaskEvent() {
        // Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

        // When adding a new task
        tasksViewModel.addNewTask()

        // Then the new task event is triggered
        val value = tasksViewModel.newTaskEvent.getOrAwaitValue()

        assertThat(value.getContentIfNotHandled(), not(nullValue()))


    }

}
  1. अपना कोड चलाएं और टेस्ट पास देखें!

अब जब आपने टेस्ट # लिखने का तरीका देख लिया है, तो खुद एक टेस्ट लिखें. इस कदम में, आपने जो कौशल सीखें हैं उनका इस्तेमाल करके एक और TasksViewModel टेस्ट लिखें.

पहला चरण. अपना ViewModel टेस्ट लिखना

आप setFilterAllTasks_tasksAddViewVisible() लिखेंगे. इस टेस्ट से यह जांच होगी कि क्या आपने सभी टास्क दिखाने के लिए फ़िल्टर टाइप सेट किया है, कि टास्क जोड़ें बटन दिखता है.

  1. रेफ़रंस के लिए addNewTask_setsNewTaskEvent() का इस्तेमाल करके, TasksViewModelTest में setFilterAllTasks_tasksAddViewVisible() नाम की एक जांच लिखें. इससे ALL_TASKS पर फ़िल्टर मोड सेट हो जाएगा और यह पक्का होगा कि tasksAddViewVisible लाइव डेटा true है.


शुरू करने के लिए नीचे दिए गए कोड का इस्तेमाल करें.

TasksViewModelTest

    @Test
    fun setFilterAllTasks_tasksAddViewVisible() {

        // Given a fresh ViewModel

        // When the filter type is ALL_TASKS

        // Then the "Add task" action is visible
        
    }

ध्यान दें:

  • सभी टास्क के लिए TasksFilterType enum ALL_TASKS. होता है
  • किसी टास्क को जोड़ने के लिए, कौनसा बटन दिखे, यह LiveData tasksAddViewVisible. कंट्रोल करता है
  1. अपना टेस्ट चलाएं.

दूसरा चरण. अपने टेस्ट की तुलना सॉल्यूशन से करें

अपने समाधान की तुलना नीचे दिए गए समाधान से करें.

TasksViewModelTest

    @Test
    fun setFilterAllTasks_tasksAddViewVisible() {

        // Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

        // When the filter type is ALL_TASKS
        tasksViewModel.setFiltering(TasksFilterType.ALL_TASKS)

        // Then the "Add task" action is visible
        assertThat(tasksViewModel.tasksAddViewVisible.getOrAwaitValue(), `is`(true))
    }

देखें कि आप ये काम करते हैं या नहीं:

  • आप उसी AndroidX ApplicationProvider.getApplicationContext() स्टेटमेंट का इस्तेमाल करके tasksViewModel बनाते हैं.
  • आप setFiltering तरीके को कॉल करते हैं, जो ALL_TASKS फ़िल्टर टाइप के इनम में पास होता है.
  • आप getOrAwaitNextValue तरीके का इस्तेमाल करके, tasksAddViewVisible के सही होने की जांच करते हैं.

तीसरा चरण. @Before नियम जोड़ें

ध्यान दें कि दोनों टेस्ट की शुरुआत में, आप TasksViewModel के बारे में बताते हैं.

TasksViewModelTest

        // Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

अगर आपने एक से ज़्यादा टेस्ट के लिए बार-बार सेट अप कोड डाला है, तो आप सेट अप का तरीका बनाने के लिए @Before एनोटेशन का इस्तेमाल कर सकते हैं और दोहराया गया कोड हटा सकते हैं. ये सभी जांच, TasksViewModel की जांच करने के लिए हैं और इसके लिए व्यू मॉडल ज़रूरी है, इसलिए इस कोड को @Before ब्लॉक में ले जाएं.

  1. tasksViewModel| इंस्टेंस lateinit इंस्टेंस वैरिएबल बनाएं.
  2. setupViewModel नाम की प्रोसेस बनाएं.
  3. @Before के साथ इसकी व्याख्या करें.
  4. व्यू मॉडल इंस्टैंशिएशन कोड को setupViewModel पर ले जाएं.

TasksViewModelTest

    // Subject under test
    private lateinit var tasksViewModel: TasksViewModel

    @Before
    fun setupViewModel() {
        tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
    }
  1. अपना कोड चलाएं!

चेतावनी

ये करें, शुरू न करें

tasksViewModel

इसकी परिभाषा के साथ:

val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

इससे, सभी जांचों के लिए एक ही इंस्टेंस का इस्तेमाल होगा. आपको यह नहीं करना चाहिए, क्योंकि हर जांच में विषय के नए इंस्टेंस होने चाहिए. इस मामले में ViewModel.

TasksViewModelTest के लिए आपका आखिरी कोड, नीचे दिया गया कोड जैसा दिखना चाहिए.

TasksViewModelTest

@RunWith(AndroidJUnit4::class)
class TasksViewModelTest {

    // Subject under test
    private lateinit var tasksViewModel: TasksViewModel

    // Executes each task synchronously using Architecture Components.
    @get:Rule
    var instantExecutorRule = InstantTaskExecutorRule()

    @Before
    fun setupViewModel() {
        tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
    }


    @Test
    fun addNewTask_setsNewTaskEvent() {

        // When adding a new task
        tasksViewModel.addNewTask()

        // Then the new task event is triggered
        val value = tasksViewModel.newTaskEvent.awaitNextValue()
        assertThat(
            value?.getContentIfNotHandled(), (not(nullValue()))
        )
    }

    @Test
    fun getTasksAddViewVisible() {

        // When the filter type is ALL_TASKS
        tasksViewModel.setFiltering(TasksFilterType.ALL_TASKS)

        // Then the "Add task" action is visible
        assertThat(tasksViewModel.tasksAddViewVisible.awaitNextValue(), `is`(true))
    }
    
}

शुरू किए गए कोड और आखिरी कोड के बीच का अंतर देखने के लिए यहां क्लिक करें.

खत्म हो चुके कोडलैब के लिए कोड डाउनलोड करने के लिए, नीचे दिए गए git कमांड का इस्तेमाल करें:

$ git clone https://github.com/googlecodelabs/android-testing.git
$ cd android-testing
$ git checkout end_codelab_1


इसके अलावा, आप रिपॉज़िटरी को एक ZIP फ़ाइल के रूप में डाउनलोड कर सकते हैं, इसे अनज़िप कर सकते हैं, और Android Studio में खोल सकते हैं.

पिन डाउनलोड करें

इस कोडलैब में यह जानकारी दी गई है:

  • Android Studio से जांच चलाने का तरीका.
  • स्थानीय (test) और इंस्ट्रूमेंटेशन टेस्ट (androidTest) के बीच का अंतर.
  • JUnit और Hamcrest का इस्तेमाल करके लोकल यूनिट टेस्ट कैसे लिखें.
  • AndroidX टेस्ट लाइब्रेरी की मदद से ViewModel टेस्ट सेट अप करना.

Udcity कोर्स:

Android डेवलपर दस्तावेज़:

वीडियो:

अन्य:

इस कोर्स में दिए गए दूसरे कोडलैब के लिंक के लिए, Kotlin कोडलैब के लैंडिंग पेज में ऐडवांस्ड Android देखें.