एस्प्रेसो (कॉफ़ी) के बारे में बुनियादी बातें

यह दस्तावेज़ बताता है कि एस्प्रेसो एपीआई.

Espresso API जांच करने वाले लेखकों को यह सोचने के लिए बढ़ावा देता है कि कोई उपयोगकर्ता क्या कर सकता है ऐप्लिकेशन के साथ इंटरैक्ट करते समय करें - यूज़र इंटरफ़ेस (यूआई) एलिमेंट का पता लगाना और उनके साथ बातचीत करें. साथ ही, यह फ़्रेमवर्क, गतिविधियों को सीधे तौर पर ऐक्सेस करने से रोकता है साथ ही, आप उन ऑब्जेक्ट को बनाए रखने और उनका उपयोग करने के लिए के साथ-साथ यूआई थ्रेड भी है. इस तरह, आपको Espresso API में getView() और getCurrentActivity() जैसे तरीके नहीं दिखते. हालांकि, आपके पास व्यू को सुरक्षित तरीके से इस्तेमाल करने का विकल्प है. इसके लिए, इन सब-क्लास को लागू किया जा सकता है ViewAction और ViewAssertion.

एपीआई कॉम्पोनेंट

Espresso के मुख्य कॉम्पोनेंट में ये शामिल हैं:

  • Espresso – व्यू के साथ इंटरैक्शन के लिए एंट्री पॉइंट (onView() और onData()). इससे ऐसे एपीआई भी दिखते हैं जो ज़रूरी तौर पर किसी भी व्यू से नहीं जुड़े हों, जैसे कि pressBack() के तौर पर.
  • ViewMatchers – ऐसे ऑब्जेक्ट का कलेक्शन जो Matcher<? super View> इंटरफ़ेस. आप इनमें से एक या उससे ज़्यादा को मौजूदा व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) में व्यू ढूंढने के लिए, onView() तरीका.
  • Viewकार्रवाइयांViewAction ऑब्जेक्ट का कलेक्शन, जिसे पास किया जा सकता है ViewInteraction.perform() तरीके, जैसे कि click().
  • ViewAssertionsViewAssertion ऑब्जेक्ट का कलेक्शन ने ViewInteraction.check() तरीका पास किया है. ज़्यादातर मामलों में, आपको दावे से मेल खाता है, जो फ़िलहाल, चुना गया व्यू.

उदाहरण:

KotlinJava
// 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() को कॉल करने जितना आसान है:

KotlinJava
onView(withId(R.id.my_view))
onView(withId(R.id.my_view));

कभी-कभी, 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!". आप संयोजन का उपयोग करके अपनी खोज को सीमित करने के लिए इसका उपयोग कर सकते हैं मैचर:

KotlinJava
onView(allOf(withId(R.id.my_view), withText("Hello!")))
onView(allOf(withId(R.id.my_view), withText("Hello!")));

आपके पास किसी भी मैचर को उलटा न करने का विकल्प भी होता है:

KotlinJava
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 के इंस्टेंस एक्ज़ीक्यूट करें.

उदाहरण के लिए, व्यू पर क्लिक करने के लिए:

KotlinJava
onView(...).perform(click())
onView(...).perform(click());

एक परफ़ॉर्म करने वाले कॉल के साथ, एक से ज़्यादा कार्रवाइयां की जा सकती हैं:

KotlinJava
onView(...).perform(typeText("Hello"), click())
onView(...).perform(typeText("Hello"), click());

अगर जिस व्यू के साथ काम किया जा रहा है वह ScrollView (वर्टिकल या हॉरिज़ॉन्टल), पिछली कार्रवाइयों पर विचार करें जिनके लिए व्यू की ज़रूरत होती है scrollTo() के साथ दिखाई जाती है, जैसे कि click() और typeText(). यह पक्का करता है कि अन्य कार्रवाई करने से पहले व्यू दिखे:

KotlinJava
onView(...).perform(scrollTo(), click())
onView(...).perform(scrollTo(), click());

ViewActions देखें .

व्यू दावे देखें

check() का इस्तेमाल करके, चुने गए मौजूदा व्यू पर दावे लागू किए जा सकते हैं तरीका. matches() दावा, सबसे ज़्यादा इस्तेमाल किया गया दावा है. यह चुने गए मौजूदा व्यू की स्थिति पर दावा करने के लिए ViewMatcher ऑब्जेक्ट.

उदाहरण के लिए, यह देखने के लिए कि व्यू में "Hello!" टेक्स्ट है या नहीं:

KotlinJava
onView(...).check(matches(withText("Hello!")))
onView(...).check(matches(withText("Hello!")));

अगर आपको यह दावा करना है कि "Hello!" व्यू का कॉन्टेंट है, तो इसे गलत तरीका माना जाएगा:

KotlinJava
// 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 यूनीक है.

KotlinJava
onView(withId(R.id.button_simple))
onView(withId(R.id.button_simple));

अब क्लिक करने के लिए:

KotlinJava
onView(withId(R.id.button_simple)).perform(click())
onView(withId(R.id.button_simple)).perform(click());

TextView टेक्स्ट की पुष्टि करें

पुष्टि करने के लिए टेक्स्ट के साथ TextView में एक यूनीक R.id भी है:

KotlinJava
onView(withId(R.id.text_simple))
onView(withId(R.id.text_simple));

अब कॉन्टेंट के टेक्स्ट की पुष्टि करने के लिए:

KotlinJava
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() का इस्तेमाल करने का सुझाव दिया जाता है आइटम से मेल खा रही है.

आइटम का चुनाव खोलें

KotlinJava
onView(withId(R.id.spinner_simple)).perform(click())
onView(withId(R.id.spinner_simple)).perform(click());

कोई आइटम चुनना

किसी आइटम को चुनने के लिए, Spinner अपने कॉन्टेंट का इस्तेमाल करके ListView बनाता है. यह व्यू बहुत लंबा हो सकता है और हो सकता है कि व्यू में एलिमेंट का योगदान न हो हैरारकी है. onData() का इस्तेमाल करके, हम अपने मनचाहे एलिमेंट को व्यू में दिखाते हैं हैरारकी है. Spinner में मौजूद आइटम, स्ट्रिंग हैं, इसलिए हम एक आइटम का मिलान करना चाहते हैं जो स्ट्रिंग "Americano" के बराबर है:

KotlinJava
onData(allOf(`is`(instanceOf(String::class.java)),
       
`is`("Americano"))).perform(click())
onData(allOf(is(instanceOf(String.class)), is("Americano"))).perform(click());

पुष्टि करें कि टेक्स्ट सही है

KotlinJava
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 का इस्तेमाल करने के बारे में ज़्यादा जानकारी के लिए, इन संसाधनों को देखें.

सैंपल