यह कोडलैब, Kotlin में बेहतर Android का हिस्सा है. अगर आप कोडलैब के क्रम में काम करते हैं, लेकिन यह ज़रूरी नहीं है, तो आपको इस कोर्स का पूरा फ़ायदा मिलेगा. सभी कोर्स कोडलैब Kotlin कोडलैब के लैंडिंग पेज पर बेहतर Android पेज पर दिए गए हैं.
परिचय
जब आपने अपने पहले ऐप्लिकेशन की पहली सुविधा लागू की थी, तो हो सकता है कि आपने कोड चलाकर यह पुष्टि की हो कि वह उम्मीद के मुताबिक काम कर रहा है. आपने टेस्ट किया, हालांकि मैन्युअल टेस्ट किया. जैसे-जैसे आप सुविधाएं जोड़ते और अपडेट करते जाएंगे, आपका कोड भी चलता रहेगा और उसकी पुष्टि होती रहेगी. हालांकि, मैन्युअल रूप से हर बार ऐसा करते समय आप थकावट करते हैं, गलतियां करते हैं, और यह बड़े पैमाने पर नहीं होता है.
कंप्यूटर स्केलिंग और ऑटोमेशन में बहुत अच्छे हैं! इसलिए, बड़ी और छोटी कंपनियों के डेवलपर अपने-आप होने वाली जांच लिखते हैं, जो कि ऐसी जांच होती हैं जिन्हें सॉफ़्टवेयर चलाता है और जिनके लिए आपको कोड के काम की पुष्टि करने के लिए ऐप्लिकेशन को मैन्युअल तरीके से चलाने की ज़रूरत नहीं होती.
कोडलैब की इस सीरीज़ में आप क्या सीख सकते हैं, यह सीखना है कि असल दुनिया में मौजूद ऐप्लिकेशन के लिए, टेस्ट का संग्रह कैसे बनाते हैं (इसे टेस्टिंग सुइट) के नाम से जाना जाता है.
इस पहले कोडलैब में Android पर जांच से जुड़ी बुनियादी बातें शामिल हैं, आप अपनी पहली जांच लिखेंगे और LiveData
और ViewModel
की जांच करने का तरीका जानेंगे.
आपको क्या पता होना चाहिए
आपको इनके बारे में पता होना चाहिए:
- Kotlin प्रोग्रामिंग लैंग्वेज
- ये मुख्य Android Jetpack लाइब्रेरी:
ViewModel
औरLiveData
- ऐप्लिकेशन आर्किटेक्चर की गाइड और Android की बुनियादी जानकारी वाले कोडलैब से मिले पैटर्न के हिसाब से, ऐप्लिकेशन का आर्किटेक्चर
आप इन चीज़ों के बारे में जानेंगे
आपको इन विषयों के बारे में जानकारी मिलेगी:
- 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 का इस्तेमाल करता है. अगर आप इन उदाहरणों में से किसी एक के बारे में जानते हैं, तो इस ऐप्लिकेशन का आर्किटेक्चर भी ऐसा ही है:
- व्यू कोडलैब (कोड बनाना सीखना) वाला कमरा
- Android Kotlin से जुड़ी बुनियादी ट्रेनिंग के लिए कोडलैब
- Android ट्रेनिंग के लिए बेहतर कोडलैब
- Android सनफ़्लावर का नमूना
- Kotlin Udacity ट्रेनिंग कोर्स की मदद से, Android ऐप्लिकेशन डेवलप करना
किसी खास लेयर के लॉजिक की पूरी जानकारी देने के बजाय, यह ज़रूरी है कि आप ऐप्लिकेशन की सामान्य आर्किटेक्चर को समझें.
यहां उन पैकेज की खास जानकारी दी गई है, जिन्हें आप #39:
पैकेज: | |
| टास्क की स्क्रीन जोड़ना या उसमें बदलाव करना: किसी टास्क को जोड़ने या उसमें बदलाव करने के लिए, यूज़र इंटरफ़ेस (यूआई) का लेयर कोड. |
| डेटा लेयर: यह टास्क के डेटा लेयर से जुड़ा होता है. इसमें डेटाबेस, नेटवर्क, और रिपॉज़िटरी कोड शामिल होता है. |
| आंकड़ों की स्क्रीन: आंकड़ों की स्क्रीन के लिए यूज़र इंटरफ़ेस (यूआई) कोड. |
| टास्क की जानकारी वाली स्क्रीन: किसी एक टास्क के लिए यूज़र इंटरफ़ेस (यूआई) का लेयर कोड. |
| टास्क टास्क: सभी टास्क की सूची के लिए यूज़र इंटरफ़ेस (यूआई) का कोड. |
| उपयोगिता क्लास: ऐप्लिकेशन के अलग-अलग हिस्सों में इस्तेमाल की जाने वाली 'शेयर की गई क्लास', जैसे कि एक से ज़्यादा स्क्रीन पर इस्तेमाल किए जाने वाले स्वाइप रीफ़्रेश लेआउट के लिए. |
डेटा स्तर (.data)
इस ऐप्लिकेशन में, रिमोट पैकेज में एक सिम्युलेटेड नेटवर्किंग लेयर और लोकल पैकेज में एक डेटाबेस लेयर शामिल होती है. आसानी से कहें, तो इस प्रोजेक्ट में नेटवर्किंग लेयर को असल नेटवर्क अनुरोध करने के बजाय, देरी से सिर्फ़ HashMap
के साथ सिम्युलेट किया जाता है.
DefaultTasksRepository
नेटवर्किंग लेयर और डेटाबेस लेयर के बीच निर्देशांक या मीडिएट करता है. साथ ही, यह यूआई लेयर में डेटा दिखाता है.
यूज़र इंटरफ़ेस (यूआई) लेयर ( .addedittask, .आंकड़े, .taskdetail, .tasks)
हर यूज़र इंटरफ़ेस (यूआई) लेयर पैकेज में एक फ़्रैगमेंट और एक व्यू मॉडल होता है. इसके अलावा, यूज़र इंटरफ़ेस (यूआई) के लिए ज़रूरी अन्य क्लास भी होती हैं (जैसे कि टास्क सूची के लिए कोई अडैप्टर). TaskActivity
वह गतिविधि है जिसमें सभी फ़्रैगमेंट शामिल होते हैं.
नेविगेशन
ऐप्लिकेशन के लिए नेविगेशन को नेविगेशन कॉम्पोनेंट से कंट्रोल किया जाता है. यह nav_graph.xml
फ़ाइल में बताया गया है. नेविगेशन Event
क्लास का इस्तेमाल करके व्यू मॉडल में ट्रिगर होता है; व्यू मॉडल यह भी तय करते हैं कि कौनसे पास करने हैं. फ़्रैगमेंट Event
की निगरानी करते हैं और स्क्रीन के बीच असल नेविगेशन करते हैं.
इस टास्क में, आप #39;अपना पहला टेस्ट चलाएं.
- 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 को हरे और लाल त्रिभुज के आइकॉन के साथ दिखाया जाता है.
पहला चरण: स्थानीय जांच करना
test
फ़ोल्डर को तब तक खोलें, जब तक आपको ExampleUnitTest.kt फ़ाइल नहीं मिल जाती.- इस पर दायां क्लिक करें और ExampleUnitTest चलाएं चुनें.
आपको स्क्रीन के सबसे नीचे, चलाएं विंडो में यह आउटपुट दिखेगा:
- हरे चेकमार्क पर ध्यान दें और जांच के नतीजों को बड़ा करके यह पक्का करें कि
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 के बराबर है.
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
}
}
- जांच करना.
- जांच के नतीजों में, जांच के आगे X देखें.
- यह भी ध्यान रखें:
- किसी एक दावे पर कार्रवाई न हो पाने की वजह से उसकी जांच नहीं की जा सकती.
- आपको अनुमानित वैल्यू (3) बनाम उस वैल्यू के बारे में बताया जाता है जो असल में कैलकुलेट की गई थी (2).
- आपको विफल दावे
(ExampleUnitTest.kt:16)
की लाइन पर भेजा जाता है.
तीसरा चरण: इंस्ट्रूमेंटल टेस्ट चलाना
इंस्ट्रुमेंटेड टेस्ट, androidTest
सोर्स सेट में हैं.
androidTest
स्रोत सेट खोलें.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: टेस्ट क्लास बनाना
main
सोर्स सेट में,todoapp.statistics
के अंदरStatisticsUtils.kt
खोलें.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 में आपको ऐसे टूल मिलते हैं जो टेस्ट स्टब जनरेट करते हैं. इससे आपको इस फ़ंक्शन के लिए टेस्ट लागू करने में मदद मिलती है.
- दायां क्लिक करें
getActiveAndCompletedStats
और Generate > Test चुनें.
टेस्ट बनाएं डायलॉग खुलता है:
- क्लास के नाम: को
StatisticsUtilsTest
में बदलें (StatisticsUtilsKtTest
के बजाय; यह यूआरएल #39 होता है, जो कि टेस्ट क्लास के नाम में KT नहीं होता). - बाकी डिफ़ॉल्ट सेटिंग रखें. JUnit 4 टेस्ट करने के लिए सही लाइब्रेरी है. डेस्टिनेशन पैकेज सही है (यह
StatisticsUtils
क्लास की जगह की जानकारी देता है) और आपको किसी एक चेक बॉक्स में सही का निशान लगाने की ज़रूरत नहीं है. ये सिर्फ़ अतिरिक्त कोड जनरेट करते हैं. हालांकि, आप अपना टेस्ट बिल्कुल शुरू से लिखेंगे. - ठीक है दबाएं
डिलीवरी की डायरेक्ट्री चुनें डायलॉग खुलता है:
आप #स्थानीय टेस्ट कर रहे हैं, क्योंकि आपके फ़ंक्शन के ज़रिए गणित का हिसाब लगाया जा रहा है और इसमें कोई Android कोड शामिल नहीं किया जाएगा. इसलिए, इसे किसी असली या एम्युलेट किए गए डिवाइस पर चलाने की ज़रूरत नहीं है.
test
डायरेक्ट्री (न किandroidTest
) चुनें, क्योंकि आप स्थानीय टेस्ट लिख रहे हैं.- ठीक है पर क्लिक करें.
- ध्यान दें कि
test/statistics/
मेंStatisticsUtilsTest
क्लास जनरेट की गई.
दूसरा चरण: जांच के लिए अपना पहला फ़ंक्शन लिखना
आप एक जांच लिखने वाले हैं, जो:
- अगर कोई पूरा हो चुका टास्क न हो और एक चालू टास्क हो,
- चालू जांच का प्रतिशत 100% है,
- और पूरे हो चुके टास्क का प्रतिशत 0% है.
StatisticsUtilsTest
खोलें.getActiveAndCompletedStats_noCompleted_returnsHundredZero
नाम का फ़ंक्शन बनाएं.
आंकड़ेUtilsTest.kt
class StatisticsUtilsTest {
fun getActiveAndCompletedStats_noCompleted_returnsHundredZero() {
// Create an active task
// Call your function
// Check the result
}
}
- टेस्ट का संकेत देने के लिए, फ़ंक्शन के नाम के ऊपर
@Test
एनोटेशन जोड़ें. यह टेस्ट ##39 होता है. - टास्क की सूची बनाएं.
// Create an active task
val tasks = listOf<Task>(
Task("title", "desc", isCompleted = false)
)
- इन टास्क के साथ,
getActiveAndCompletedStats
पर कॉल करें.
// Call your function
val result = getActiveAndCompletedStats(tasks)
- दावों का इस्तेमाल करके, देखें कि
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)
}
}
- टेस्ट चलाएं (
StatisticsUtilsTest
पर क्लिक करें और चलाएं).
इसे पास होना चाहिए:
तीसरा चरण: Hamcrest डिपेंडेंसी जोड़ना
आपका टेस्ट, आपके कोड के काम करने के दस्तावेज़ के तौर पर काम करता है. इसलिए, लोग इन्हें आसानी से पढ़ सकते हैं. इन दो दावों की तुलना करें:
assertEquals(result.completedTasksPercent, 0f)
// versus
assertThat(result.completedTasksPercent, `is`(0f))
दूसरा दावा, इंसान के वाक्य की तरह दिखता है. इसे Hamcrest नाम के दावे वाले फ़्रेमवर्क का इस्तेमाल करके लिखा गया है. पढ़ने लायक दावे लिखने का एक और अच्छा टूल ट्रूथ लाइब्रेरी है. आप इस कोडलैब में हैमक्रेस्ट का इस्तेमाल करके, दावे दर्ज करेंगे.
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 का इस्तेमाल करें
assertEquals
के बजाय Hamcrest'sassertThat
का इस्तेमाल करने के लिए,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))
}
}
- अपडेट किया गया टेस्ट चलाएं, ताकि यह पक्का हो सके कि यह अब भी काम कर रहा है!
यह कोडलैब आपको हैम ऊंचाई की पूरी जानकारी नहीं देएगा. इसलिए, अगर आप #39;ज़्यादा जानना चाहते हैं, तो आधिकारिक ट्यूटोरियल देखें.
यह प्रैक्टिस के लिए, वैकल्पिक टास्क है.
इस टास्क में, आप JUnit और Hamcrest का इस्तेमाल करके ज़्यादा टेस्ट लिखेंगे. आप भी टेस्ट ड्राइव डेवलपमेंट प्रोग्राम की रणनीति का इस्तेमाल करके, टेस्ट लिखेंगे. टेस्ट ड्रिवन डेवलपमेंट या टीडीडी, प्रोग्रामिंग का एक स्कूल है, जिसमें आपका फ़ीचर कोड लिखने के बजाय सबसे पहले टेस्ट लिखने की बात कही जाती है. फिर आप अपना टेस्ट कोड पास करने के लक्ष्य के साथ अपना फ़ीचर कोड लिखते हैं.
पहला चरण. टेस्ट लिखना
जब आपके पास सामान्य टास्क की सूची हो, तब जांच लिखें:
- अगर एक पूरा हो चुका कोई टास्क नहीं है, तो
activeTasks
टास्क0f
होना चाहिए, और पूरे हो चुके टास्क का प्रतिशत100f
होना चाहिए . - अगर पूरे हो चुके दो टास्क और तीन चालू टास्क हैं, तो पूरा हो चुका प्रतिशत
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; टेस्ट-ड्रिवन डेवलपमेंट का इस्तेमाल करेंगे. टेस्ट पर आधारित डेवलपमेंट इन चरणों के मुताबिक होना चाहिए.
- दिया गया, कब, फिर स्ट्रक्चर का इस्तेमाल करके, टेस्ट करें और नाम को फ़ॉलो करने वाले नाम से लिखें.
- टेस्ट फ़ेल हो जाने की पुष्टि करें.
- टेस्ट पास करने के लिए कम से कम कोड लिखें.
- सभी टेस्ट के लिए दोहराएं!
गड़बड़ी को ठीक करने के बजाय, टेस्ट सबसे पहले लिखें. इसके बाद, आप इस बात की पुष्टि कर सकते हैं कि आने वाले समय में कभी भी गलती से दोबारा आने वाले टेस्ट से आपको सुरक्षा मिल सके.
- अगर कोई खाली सूची
emptyList()
है, तो दोनों प्रतिशत 0f होना चाहिए. - अगर टास्क लोड करने में कोई गड़बड़ी हुई, तो सूची
null
होगी और दोनों प्रतिशत 0f होने चाहिए. - अपने टेस्ट चलाएं और पुष्टि करें कि वे काम नहीं करते:
तीसरा चरण. गड़बड़ी ठीक करें
अब अपनी जांच के लिए, गड़बड़ी ठीक करें.
- अगर
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
)
}
}
- अपने टेस्ट फिर से चलाएं और पुष्टि करें कि अब सभी टेस्ट पास हो गए हैं!
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
के लिए कोई टेस्ट फ़ाइल बनाएं.
- आप जिस कक्षा की जांच करना चाहते हैं उसे
tasks
पैकेज,TasksViewModel.
में खोलें - कोड में, क्लास के नाम पर दायां क्लिक करें
TasksViewModel
-> जनरेट करें -> जांच करें.
- टेस्ट बनाएं स्क्रीन पर, स्वीकार करने के लिए ठीक है पर क्लिक करें (कोई भी डिफ़ॉल्ट सेटिंग बदलने की ज़रूरत नहीं).
- डेस्टिनेशन डायरेक्ट्री चुनें डायलॉग पर, जांच डायरेक्ट्री चुनें.
दूसरा चरण. अपना ViewModel टेस्ट लिखना शुरू करें
इस कदम में आप व्यू व्यू मॉडल की जांच करते हैं. इससे यह पता चलता है कि addNewTask
तरीके को कॉल करने पर, नए टास्क विंडो को खोलने के लिए Event
चालू हो जाता है.
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 टेस्ट सही तरीके से सेट अप करने के लिए यह तरीका अपनाएं:
- AndroidX टेस्ट को मुख्य और एक्सपेंडेंसी जोड़ें
- Robolectric टेस्टिंग लाइब्रेरी निर्भरता जोड़ें
- AndroidJunit4 टेस्ट रनर से क्लास को एनोटेट करना
- AndroidX टेस्ट कोड लिखें
आप ये चरण पूरे करने वाले हैं और फिर आप दोनों के मिलकर काम करने के तरीके को समझ जाएंगे.
तीसरा चरण. Gradle डिपेंडेंसी जोड़ना
- इन 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 टेस्ट रनर जोड़ें
@RunWith(AndroidJUnit4::class)
को अपनी टेस्ट क्लास के ऊपर जोड़ें.
TasksViewModelTest.kt
@RunWith(AndroidJUnit4::class)
class TasksViewModelTest {
// Test code
}
चरण 5. AndroidX टेस्ट का इस्तेमाल करना
अब आप AndroidX टेस्ट लाइब्रेरी का इस्तेमाल कर सकते हैं. इसमें ऐसा तरीका ApplicationProvider.getApplicationContex
t
शामिल है जिसमें ऐप्लिकेशन के बारे में जानकारी दी जाती है.
- AndroidX टेस्ट लाइब्रेरी से
ApplicationProvider.getApplicationContext()
का इस्तेमाल करकेTasksViewModel
बनाएं.
TasksViewModelTest.kt
// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
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
}
- पुष्टि करें कि यह काम करता है या नहीं, इसकी जांच करने के लिए चलाएं.
कॉन्सेप्ट: 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
चेतावनी को ठीक कर सकते हैं.
- अपनी 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
को टेस्ट करने के लिए दो तरीकों का सुझाव दिया जाता है:
InstantTaskExecutorRule
का इस्तेमाल करें- पक्का करें कि
LiveData
निगरानी
पहला चरण. InstantTaskExecutorRule इस्तेमाल करें
InstantTaskExecutorRule
JUnit का नियम है. जब आप @get:Rule
एनोटेशन के साथ इसका इस्तेमाल करते हैं, तो InstantTaskExecutorRule
क्लास में कुछ कोड, जांच से पहले और बाद में चलते हैं. (असल कोड देखने के लिए, कीबोर्ड शॉर्टकट Command+B का इस्तेमाल करके फ़ाइल देखी जा सकती है).
यह नियम एक ही थ्रेड में, आर्किटेक्चर कॉम्पोनेंट से जुड़े सभी बैकग्राउंड जॉब चलाता है, ताकि टेस्ट के नतीजे सिंक होते रहें और उन्हें दोहराया जा सके. जब आप लाइव डेटा की जांच वाले टेस्ट लिखते हैं, तो इस नियम का इस्तेमाल करें!
- आर्किटेक्चर कॉम्पोनेंट कॉम्पोनेंट कोर टेस्टिंग लाइब्रेरी (जिसमें यह नियम शामिल है) के लिए, ग्रेडल डिपेंडेंसी जोड़ें.
app/build.gradle
testImplementation "androidx.arch.core:core-testing:$archTestingVersion"
TasksViewModelTest.kt
खोलें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
नाम का एक एक्सटेंशन फ़ंक्शन बनाने वाले हैं, ताकि ऑब्ज़र्वर जोड़ना आसान हो सके.
- अपने
test
सोर्स सेट में,LiveDataTestUtil.kt
नाम की एक नई Kotlin फ़ाइल बनाएं.
- कोड को कॉपी करके नीचे चिपकाएं.
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
ट्रिगर हुआ था.
getOrAwaitValue
का इस्तेमाल करकेnewTaskEvent
के लिएLiveData
वैल्यू पाएं.
val value = tasksViewModel.newTaskEvent.getOrAwaitValue()
- दावा करें कि वैल्यू शून्य नहीं है.
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()))
}
}
- अपना कोड चलाएं और टेस्ट पास देखें!
अब जब आपने टेस्ट # लिखने का तरीका देख लिया है, तो खुद एक टेस्ट लिखें. इस कदम में, आपने जो कौशल सीखें हैं उनका इस्तेमाल करके एक और TasksViewModel
टेस्ट लिखें.
पहला चरण. अपना ViewModel टेस्ट लिखना
आप setFilterAllTasks_tasksAddViewVisible()
लिखेंगे. इस टेस्ट से यह जांच होगी कि क्या आपने सभी टास्क दिखाने के लिए फ़िल्टर टाइप सेट किया है, कि टास्क जोड़ें बटन दिखता है.
- रेफ़रंस के लिए
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
enumALL_TASKS.
होता है - किसी टास्क को जोड़ने के लिए, कौनसा बटन दिखे, यह
LiveData
tasksAddViewVisible.
कंट्रोल करता है
- अपना टेस्ट चलाएं.
दूसरा चरण. अपने टेस्ट की तुलना सॉल्यूशन से करें
अपने समाधान की तुलना नीचे दिए गए समाधान से करें.
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
ब्लॉक में ले जाएं.
tasksViewModel|
इंस्टेंसlateinit
इंस्टेंस वैरिएबल बनाएं.setupViewModel
नाम की प्रोसेस बनाएं.@Before
के साथ इसकी व्याख्या करें.- व्यू मॉडल इंस्टैंशिएशन कोड को
setupViewModel
पर ले जाएं.
TasksViewModelTest
// Subject under test
private lateinit var tasksViewModel: TasksViewModel
@Before
fun setupViewModel() {
tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
}
- अपना कोड चलाएं!
चेतावनी
ये न करें, शुरू न करें
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 डेवलपर दस्तावेज़:
- ऐप्लिकेशन के आर्किटेक्चर की गाइड
- जेयूनिट4
- हैम्रेस्ट
- रोबोलेट्रिक टेस्टिंग लाइब्रेरी
- AndroidX टेस्ट लाइब्रेरी
- AndroidX आर्किटेक्चर कॉम्पोनेंट कोर टेस्ट लाइब्रेरी
- स्रोत सेट
- कमांड लाइन से जांच करना
वीडियो:
अन्य:
इस कोर्स में दिए गए दूसरे कोडलैब के लिंक के लिए, Kotlin कोडलैब के लैंडिंग पेज में ऐडवांस्ड Android देखें.