यह दस्तावेज़ बताता है कि एस्प्रेसो एपीआई.
Espresso API जांच करने वाले लेखकों को यह सोचने के लिए बढ़ावा देता है कि कोई उपयोगकर्ता क्या कर सकता है
ऐप्लिकेशन के साथ इंटरैक्ट करते समय करें - यूज़र इंटरफ़ेस (यूआई) एलिमेंट का पता लगाना और
उनके साथ बातचीत करें. साथ ही, यह फ़्रेमवर्क, गतिविधियों को सीधे तौर पर ऐक्सेस करने से रोकता है
साथ ही, आप उन ऑब्जेक्ट को बनाए रखने और उनका उपयोग करने के लिए
के साथ-साथ यूआई थ्रेड भी है. इस तरह, आपको
Espresso API में getView()
और getCurrentActivity()
जैसे तरीके नहीं दिखते.
हालांकि, आपके पास व्यू को सुरक्षित तरीके से इस्तेमाल करने का विकल्प है. इसके लिए, इन सब-क्लास को लागू किया जा सकता है
ViewAction
और ViewAssertion
.
एपीआई कॉम्पोनेंट
Espresso के मुख्य कॉम्पोनेंट में ये शामिल हैं:
- Espresso – व्यू के साथ इंटरैक्शन के लिए एंट्री पॉइंट (
onView()
औरonData()
). इससे ऐसे एपीआई भी दिखते हैं जो ज़रूरी तौर पर किसी भी व्यू से नहीं जुड़े हों, जैसे किpressBack()
के तौर पर. - ViewMatchers – ऐसे ऑब्जेक्ट का कलेक्शन जो
Matcher<? super View>
इंटरफ़ेस. आप इनमें से एक या उससे ज़्यादा को मौजूदा व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) में व्यू ढूंढने के लिए,onView()
तरीका. - Viewकार्रवाइयां –
ViewAction
ऑब्जेक्ट का कलेक्शन, जिसे पास किया जा सकता हैViewInteraction.perform()
तरीके, जैसे किclick()
. - ViewAssertions –
ViewAssertion
ऑब्जेक्ट का कलेक्शन नेViewInteraction.check()
तरीका पास किया है. ज़्यादातर मामलों में, आपको दावे से मेल खाता है, जो फ़िलहाल, चुना गया व्यू.
उदाहरण:
// withId(R.id.my_view) is a ViewMatcher
// click() is a ViewAction
// matches(isDisplayed()) is a ViewAssertion
onView(withId(R.id.my_view))
.perform(click())
.check(matches(isDisplayed()))
// withId(R.id.my_view) is a ViewMatcher
// click() is a ViewAction
// matches(isDisplayed()) is a ViewAssertion
onView(withId(R.id.my_view))
.perform(click())
.check(matches(isDisplayed()));
कोई व्यू ढूंढें
ज़्यादातर मामलों में, onView()
तरीका हैमक्रेस्ट मैचर का इस्तेमाल करता है
जिनका वर्तमान दृश्य में किसी एक — और केवल एक — से मेल खाने की उम्मीद हो
हैरारकी है. मैच करने वाले लोग बहुत कारगर होते हैं और वे बेहतर तरीके से इसका इस्तेमाल कर सकते हैं
की मदद से उन्हें Mockito या JUnit में जोड़ें. अगर आपको हैमक्रेस्ट मैचर की जानकारी नहीं है, तो हम
का सुझाव है कि आप इस पर एक नज़र से
प्रज़ेंटेशन.
आम तौर पर, आपके पसंद के व्यू में एक यूनीक R.id
होता है. साथ ही, एक सामान्य withId
मैचर को
ज़्यादा सटीक तरीके से देखें. हालांकि, ऐसे कई कानूनी मामले हैं जहां आपको
टेस्ट डेवलपमेंट के समय R.id
तय नहीं किया जा सकता. उदाहरण के लिए, विशिष्ट दृश्य
हो सकता है कि R.id
न हो या R.id
सबसे अलग न हो. यह सामान्य हो सकता है
इंस्ट्रुमेंटेशन टेस्ट लिखने में नाज़ुक और मुश्किल होते हैं, क्योंकि
findViewById()
से व्यू ऐक्सेस करने की सुविधा काम नहीं करती. इस तरह, आपको
व्यू होल्ड करने वाली ऐक्टिविटी या फ़्रैगमेंट के निजी सदस्यों को ऐक्सेस करने की ज़रूरत हो या
एक ज्ञात R.id
वाला कंटेनर ढूंढ़ें और
खास व्यू.
एस्प्रेसो आपको दृश्य को सटीक बनाने की अनुमति देकर इस समस्या को अच्छी तरह से हल करता है
या तो मौजूदा ViewMatcher
ऑब्जेक्ट का इस्तेमाल करके या अपनी पसंद के मुताबिक बनाए गए ऑब्जेक्ट का इस्तेमाल करके.
उसके R.id
से कोई व्यू ढूंढना, onView()
को कॉल करने जितना आसान है:
कभी-कभी, R.id
वैल्यू एक से ज़्यादा व्यू के बीच शेयर की जाती हैं. जब ऐसा होता है, तो
किसी खास R.id
का इस्तेमाल करने की कोशिश करने पर, आपको एक अपवाद मिल सकता है, जैसे
AmbiguousViewMatcherException
. अपवाद संदेश आपको एक टेक्स्ट
मौजूदा व्यू हैरारकी (व्यू और व्यू हैरारकी) की झलक जिसे आप खोज और देख सकते हैं
व्यू जो सामान्य R.id
से मेल नहीं खाते:
java.lang.RuntimeException: androidx.test.espresso.AmbiguousViewMatcherException This matcher matches multiple views in the hierarchy: (withId: is <123456789>) ... +----->SomeView{id=123456789, res-name=plus_one_standard_ann_button, visibility=VISIBLE, width=523, height=48, has-focus=false, has-focusable=true, window-focus=true, is-focused=false, is-focusable=false, enabled=true, selected=false, is-layout-requested=false, text=, root-is-layout-requested=false, x=0.0, y=625.0, child-count=1} ****MATCHES**** | +------>OtherView{id=123456789, res-name=plus_one_standard_ann_button, visibility=VISIBLE, width=523, height=48, has-focus=false, has-focusable=true, window-focus=true, is-focused=false, is-focusable=true, enabled=true, selected=false, is-layout-requested=false, text=Hello!, root-is-layout-requested=false, x=0.0, y=0.0, child-count=1} ****MATCHES****
व्यू की अलग-अलग विशेषताओं पर नज़र डालने पर, आपको वह व्यू खास तौर पर मिल सकता है
पहचाने जा सकने वाली प्रॉपर्टी होती हैं. ऊपर दिए गए उदाहरण में, किसी एक व्यू में
"Hello!"
. आप संयोजन का उपयोग करके अपनी खोज को सीमित करने के लिए इसका उपयोग कर सकते हैं
मैचर:
onView(allOf(withId(R.id.my_view), withText("Hello!")))
onView(allOf(withId(R.id.my_view), withText("Hello!")));
आपके पास किसी भी मैचर को उलटा न करने का विकल्प भी होता है:
onView(allOf(withId(R.id.my_view), not(withText("Unwanted"))))
onView(allOf(withId(R.id.my_view), not(withText("Unwanted"))));
ViewMatchers
देखें
का इस्तेमाल करें.
ज़रूरी बातें
- अच्छी तरह काम करने वाले ऐप्लिकेशन में, ऐसे सभी व्यू जिनसे कोई उपयोगकर्ता इंटरैक्ट कर सकता है
या तो उसमें जानकारी देने वाला टेक्स्ट होना चाहिए या कॉन्टेंट का ब्यौरा होना चाहिए. यहां जाएं:
ऐप्लिकेशन को ज़्यादा सुलभ बनाना
विवरण. अगर आप
withText()
का उपयोग करके खोज को सीमित नहीं कर पा रहे हैं याwithContentDescription()
, इसे सुलभता से जुड़ी गड़बड़ी के तौर पर देखें. - कम से कम जानकारी देने वाले मैचर का इस्तेमाल करें, जो आपका खोजा जा रहा व्यू ढूंढता हो
के लिए. ज़्यादा जानकारी न दें, क्योंकि इससे फ़्रेमवर्क को ज़रूरत से ज़्यादा काम करने में मदद मिलेगी
ज़रूरी है. उदाहरण के लिए, अगर कोई व्यू अपने टेक्स्ट से अच्छी तरह से पहचाना जा सकता है, तो आपको
यह बताने की ज़रूरत नहीं है कि व्यू को
TextView
से भी असाइन किया जा सकता है. बहुत सारे व्यू के लिए,R.id
काफ़ी होना चाहिए. - अगर टारगेट व्यू
AdapterView
, जैसे किListView
में है, तोGridView
याSpinner
—ऐसा हो सकता है किonView()
तरीका काम न करे. इनमें तो आपको इसके बजायonData()
का इस्तेमाल करना चाहिए.
व्यू पर कोई कार्रवाई करना
जब आपको टारगेट व्यू के लिए कोई सही मैचर मिल जाता है, तो
परफ़ॉर्म करने के तरीके का इस्तेमाल करके, इस पर ViewAction
के इंस्टेंस एक्ज़ीक्यूट करें.
उदाहरण के लिए, व्यू पर क्लिक करने के लिए:
एक परफ़ॉर्म करने वाले कॉल के साथ, एक से ज़्यादा कार्रवाइयां की जा सकती हैं:
onView(...).perform(typeText("Hello"), click())
onView(...).perform(typeText("Hello"), click());
अगर जिस व्यू के साथ काम किया जा रहा है वह ScrollView
(वर्टिकल या
हॉरिज़ॉन्टल), पिछली कार्रवाइयों पर विचार करें जिनके लिए व्यू की ज़रूरत होती है
scrollTo()
के साथ दिखाई जाती है, जैसे कि click()
और typeText()
. यह
पक्का करता है कि अन्य कार्रवाई करने से पहले व्यू दिखे:
ViewActions
देखें
.
व्यू दावे देखें
check()
का इस्तेमाल करके, चुने गए मौजूदा व्यू पर दावे लागू किए जा सकते हैं
तरीका. matches()
दावा, सबसे ज़्यादा इस्तेमाल किया गया दावा है. यह
चुने गए मौजूदा व्यू की स्थिति पर दावा करने के लिए ViewMatcher
ऑब्जेक्ट.
उदाहरण के लिए, यह देखने के लिए कि व्यू में "Hello!"
टेक्स्ट है या नहीं:
onView(...).check(matches(withText("Hello!")))
onView(...).check(matches(withText("Hello!")));
अगर आपको यह दावा करना है कि "Hello!"
व्यू का कॉन्टेंट है, तो इसे गलत तरीका माना जाएगा:
// Don't use assertions like withText inside onView.
onView(allOf(withId(...), withText("Hello!"))).check(matches(isDisplayed()))
// Don't use assertions like withText inside onView.
onView(allOf(withId(...), withText("Hello!"))).check(matches(isDisplayed()));
दूसरी ओर, अगर आप दावा करना चाहते हैं कि "Hello!"
टेक्स्ट के साथ एक व्यू यह है
दिखाई दे—उदाहरण के लिए, व्यू के दिखने की जानकारी से जुड़े फ़्लैग में बदलाव होने के बाद—
कोड ठीक है.
सामान्य जांच का दावा देखें
इस उदाहरण में, SimpleActivity
में Button
और TextView
शामिल हैं. जब
बटन पर क्लिक करने से TextView
का कॉन्टेंट "Hello Espresso!"
में बदल जाता है.
Espresso के साथ इसकी जांच करने का तरीका:
बटन पर क्लिक करें
सबसे पहले एक ऐसी प्रॉपर्टी खोजें जिससे बटन को खोजने में मदद मिले. कॉन्टेंट बनाने
SimpleActivity
के बटन का R.id
यूनीक है.
अब क्लिक करने के लिए:
onView(withId(R.id.button_simple)).perform(click())
onView(withId(R.id.button_simple)).perform(click());
TextView टेक्स्ट की पुष्टि करें
पुष्टि करने के लिए टेक्स्ट के साथ TextView
में एक यूनीक R.id
भी है:
अब कॉन्टेंट के टेक्स्ट की पुष्टि करने के लिए:
onView(withId(R.id.text_simple)).check(matches(withText("Hello Espresso!")))
onView(withId(R.id.text_simple)).check(matches(withText("Hello Espresso!")));
अडैप्टर व्यू में डेटा लोड होने की जांच करना
AdapterView
एक खास तरह का विजेट है, जो अपना डेटा डाइनैमिक तौर पर लोड करता है
अडैप्टर. AdapterView
का सबसे सामान्य उदाहरण ListView
है. जैसे
यह LinearLayout
जैसे स्टैटिक विजेट के उलट है, जो
AdapterView
चाइल्ड एंट्री, मौजूदा व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) में लोड हो सकती हैं. आसान
onView()
खोज में ऐसे व्यू नहीं मिलेंगे जो फ़िलहाल लोड नहीं हैं.
Espresso एक अलग onData()
एंट्री पॉइंट देता है, जो कि
हम उस अडैप्टर आइटम को लोड कर पाते हैं जिसकी शिकायत की गई है. इससे उस आइटम पर फ़ोकस करने में
या उसके किसी बच्चे पर काम करने के लिए किया जा सकता है.
चेतावनी:
AdapterView
को onData()
में समस्या हो सकती है
अगर वे इनहेरिटेंस के अनुबंधों को तोड़ते हैं, तो
getItem()
एपीआई. ऐसे मामलों में, सबसे सही तरीका यह होता है कि
अपने ऐप्लिकेशन कोड को फिर से व्यवस्थित करें. अगर आप ऐसा नहीं कर सकते, तो
मिलता-जुलता कस्टम AdapterViewProtocol
. ज़्यादा जानकारी के लिए,
डिफ़ॉल्ट देखो
Espresso की AdapterViewProtocols
क्लास.
अडैप्टर व्यू सिंपल टेस्ट
इस आसान से टेस्ट से onData()
को इस्तेमाल करने का तरीका पता चलता है. SimpleActivity
में शामिल है
Spinner
में कुछ ऐसे आइटम हैं जिनमें कॉफ़ी के अलग-अलग तरह के पीने की चीज़ें दिखाई गई हैं. जब कोई
आइटम चुना गया है, एक TextView
है जो "One %s a day!"
में बदल जाता है, जहां
%s
, चुने गए आइटम के बारे में बताता है.
इस टेस्ट का मकसद Spinner
को खोलना, किसी खास आइटम को चुनना, और
पुष्टि करें कि TextView
में आइटम शामिल है. ऐसा इसलिए है, क्योंकि Spinner
क्लास
AdapterView
को, इन कामों के लिए onView()
के बजाय onData()
का इस्तेमाल करने का सुझाव दिया जाता है
आइटम से मेल खा रही है.
आइटम का चुनाव खोलें
onView(withId(R.id.spinner_simple)).perform(click())
onView(withId(R.id.spinner_simple)).perform(click());
कोई आइटम चुनना
किसी आइटम को चुनने के लिए, Spinner
अपने कॉन्टेंट का इस्तेमाल करके ListView
बनाता है.
यह व्यू बहुत लंबा हो सकता है और हो सकता है कि व्यू में एलिमेंट का योगदान न हो
हैरारकी है. onData()
का इस्तेमाल करके, हम अपने मनचाहे एलिमेंट को व्यू में दिखाते हैं
हैरारकी है. Spinner
में मौजूद आइटम, स्ट्रिंग हैं, इसलिए हम एक आइटम का मिलान करना चाहते हैं
जो स्ट्रिंग "Americano"
के बराबर है:
onData(allOf(`is`(instanceOf(String::class.java)),
`is`("Americano"))).perform(click())
onData(allOf(is(instanceOf(String.class)), is("Americano"))).perform(click());
पुष्टि करें कि टेक्स्ट सही है
onView(withId(R.id.spinnertext_simple))
.check(matches(withText(containsString("Americano"))))
onView(withId(R.id.spinnertext_simple))
.check(matches(withText(containsString("Americano"))));
डीबग करना
जांच में गड़बड़ी होने पर, Espresso को डीबग करने से जुड़ी काम की जानकारी मिलती है:
लॉग इन हो रहा है
एस्प्रेसो, व्यू वाली सभी कार्रवाइयों को Logcat में लॉग करता है. उदाहरण के लिए:
ViewInteraction: Performing 'single click' action on view with text: Espresso
व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम)
onView()
पर एस्प्रेसो, अपवाद वाले मैसेज में व्यू हैरारकी को प्रिंट करता है
विफल होता है.
- अगर
onView()
को टारगेट व्यू नहीं मिलता है, तोNoMatchingViewException
फेंका गया. विश्लेषण करने के लिए, अपवाद स्ट्रिंग में व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) की जांच की जा सकती है मैचर किसी व्यू से क्यों मैच नहीं करता. - अगर
onView()
को ऐसे कई व्यू मिलते हैं जो दिए गए मैचर से मेल खाते हैं, तोAmbiguousViewMatcherException
को थ्रो किया गया है. व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) प्रिंट हो गया है और मेल खाने वाले व्यूMATCHES
लेबल से मार्क किए गए हैं:
java.lang.RuntimeException: androidx.test.espresso.AmbiguousViewMatcherException This matcher matches multiple views in the hierarchy: (withId: is <123456789>) ... +----->SomeView{id=123456789, res-name=plus_one_standard_ann_button, visibility=VISIBLE, width=523, height=48, has-focus=false, has-focusable=true, window-focus=true, is-focused=false, is-focusable=false, enabled=true, selected=false, is-layout-requested=false, text=, root-is-layout-requested=false, x=0.0, y=625.0, child-count=1} ****MATCHES**** | +------>OtherView{id=123456789, res-name=plus_one_standard_ann_button, visibility=VISIBLE, width=523, height=48, has-focus=false, has-focusable=true, window-focus=true, is-focused=false, is-focusable=true, enabled=true, selected=false, is-layout-requested=false, text=Hello!, root-is-layout-requested=false, x=0.0, y=0.0, child-count=1} ****MATCHES****
जटिल व्यू हैरारकी या विजेट के अनचाहे व्यवहार से निपटते समय का उपयोग करना हमेशा उपयोगी होता है, इनके लिए Android Studio में क्रम के हिसाब से व्यूअर की सुविधा एक व्याख्या.
अडैप्टर व्यू से जुड़ी चेतावनियां
Espresso, उपयोगकर्ताओं को AdapterView
विजेट की मौजूदगी के बारे में चेतावनी देता है. जब onView()
ऑपरेशन से एक NoMatchingViewException
मिलता है और AdapterView
विजेट होते हैं
व्यू हैरारकी में मौजूद है, तो इसका सबसे आम समाधान है onData()
का इस्तेमाल करना.
अपवाद वाले मैसेज में अडैप्टर व्यू की सूची के साथ एक चेतावनी शामिल होगी.
टारगेट व्यू को लोड करने के लिए, इस जानकारी का इस्तेमाल onData()
को शुरू करने के लिए किया जा सकता है.
अन्य संसाधन
Android परीक्षणों में Espresso का इस्तेमाल करने के बारे में ज़्यादा जानकारी के लिए, इन संसाधनों को देखें.
सैंपल
- CustomMatcherSample:
यह दिखाता है कि किसी
EditText
ऑब्जेक्ट की संकेत प्रॉपर्टी से मैच करने के लिए, Espresso को कैसे बढ़ाया जाता है. - RecyclerViewSample:
Espresso के लिए
RecyclerView
कार्रवाइयां. - (ज़्यादा जानकारी...)