एस्प्रेसो रेसिपी

इस दस्तावेज़ में अलग-अलग तरह के एस्प्रेसो टेस्ट को सेट अप करने के तरीके के बारे में बताया गया है.

किसी दूसरे व्यू के बगल में मौजूद व्यू को मैच करना

किसी लेआउट में कुछ ऐसे व्यू हो सकते हैं जो खुद में यूनीक न हों. इसके लिए उदाहरण के लिए, संपर्क सूची में मौजूद 'बार-बार होने वाला कॉल' बटन R.id में ऐसा ही टेक्स्ट है. साथ ही, इनकी प्रॉपर्टी अन्य कॉल जैसी ही हैं बटन पर क्लिक कर सकते हैं.

उदाहरण के लिए, इस गतिविधि में, "7" टेक्स्ट वाला व्यू कई बार दोहराया जाता है पंक्तियां:

एक ही व्यू एलिमेंट की तीन कॉपी दिखाने वाली सूची गतिविधि
     3-आइटम की सूची में

अक्सर, गैर-यूनीक व्यू को किसी यूनीक लेबल के साथ जोड़ा जाएगा जैसे, कॉल बटन के बगल में मौजूद संपर्क का नाम. इस मामले में, अपना चुनाव सटीक बनाने के लिए, hasSibling() मैचर का इस्तेमाल किया जा सकता है:

KotlinJava
onView(allOf(withText("7"), hasSibling(withText("item: 0"))))
   
.perform(click())
onView(allOf(withText("7"), hasSibling(withText("item: 0"))))
   
.perform(click());

ऐक्शन बार के अंदर मौजूद व्यू को मैच करें

ActionBarTestActivity में दो अलग-अलग ऐक्शन बार हैं: सामान्य कार्रवाई बार और संदर्भ के हिसाब से कार्रवाई बार को बनाया गया है, जो विकल्प मेन्यू से बनाया गया है. दोनों ऐक्शन बार में एक आइटम हमेशा दिखता है और दो ऐसे आइटम होते हैं जो सिर्फ़ ओवरफ़्लो मेनू में दृश्यमान. जब किसी आइटम पर क्लिक किया जाता है, तो यह TextView को क्लिक किए गए आइटम का कॉन्टेंट.

दोनों ऐक्शन बार पर दिखने वाले आइकॉन को मैच करना आसान है, जैसा कि दिखाया गया है कोड स्निपेट में:

KotlinJava
fun testClickActionBarItem() {
   
// We make sure the contextual action bar is hidden.
    onView
(withId(R.id.hide_contextual_action_bar))
       
.perform(click())

   
// Click on the icon - we can find it by the r.Id.
    onView
(withId(R.id.action_save))
       
.perform(click())

   
// Verify that we have really clicked on the icon
   
// by checking the TextView content.
    onView
(withId(R.id.text_action_bar_result))
       
.check(matches(withText("Save")))
}
public void testClickActionBarItem() {
   
// We make sure the contextual action bar is hidden.
    onView
(withId(R.id.hide_contextual_action_bar))
       
.perform(click());

   
// Click on the icon - we can find it by the r.Id.
    onView
(withId(R.id.action_save))
       
.perform(click());

   
// Verify that we have really clicked on the icon
   
// by checking the TextView content.
    onView
(withId(R.id.text_action_bar_result))
       
.check(matches(withText("Save")));
}

'सेव करें' बटन, गतिविधि बार में सबसे ऊपर मौजूद होता है

कॉन्टेक्स्ट के हिसाब से दिए जाने वाले ऐक्शन बार के लिए, यह कोड एक जैसा दिखता है:

KotlinJava
fun testClickActionModeItem() {
   
// Make sure we show the contextual action bar.
    onView
(withId(R.id.show_contextual_action_bar))
       
.perform(click())

   
// Click on the icon.
    onView
((withId(R.id.action_lock)))
       
.perform(click())

   
// Verify that we have really clicked on the icon
   
// by checking the TextView content.
    onView
(withId(R.id.text_action_bar_result))
       
.check(matches(withText("Lock")))
}
public void testClickActionModeItem() {
   
// Make sure we show the contextual action bar.
    onView
(withId(R.id.show_contextual_action_bar))
       
.perform(click());

   
// Click on the icon.
    onView
((withId(R.id.action_lock)))
       
.perform(click());

   
// Verify that we have really clicked on the icon
   
// by checking the TextView content.
    onView
(withId(R.id.text_action_bar_result))
       
.check(matches(withText("Lock")));
}

लॉक बटन, कार्रवाई बार में गतिविधि के सबसे ऊपर होता है

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

सामान्य कार्रवाई बार के लिए:

KotlinJava
fun testActionBarOverflow() {
   
// Make sure we hide the contextual action bar.
    onView
(withId(R.id.hide_contextual_action_bar))
       
.perform(click())

   
// Open the options menu OR open the overflow menu, depending on whether
   
// the device has a hardware or software overflow menu button.
    openActionBarOverflowOrOptionsMenu
(
           
ApplicationProvider.getApplicationContext<Context>())

   
// Click the item.
    onView
(withText("World"))
       
.perform(click())

   
// Verify that we have really clicked on the icon by checking
   
// the TextView content.
    onView
(withId(R.id.text_action_bar_result))
       
.check(matches(withText("World")))
}
public void testActionBarOverflow() {
   
// Make sure we hide the contextual action bar.
    onView
(withId(R.id.hide_contextual_action_bar))
       
.perform(click());

   
// Open the options menu OR open the overflow menu, depending on whether
   
// the device has a hardware or software overflow menu button.
    openActionBarOverflowOrOptionsMenu
(
           
ApplicationProvider.getApplicationContext());

   
// Click the item.
    onView
(withText("World"))
       
.perform(click());

   
// Verify that we have really clicked on the icon by checking
   
// the TextView content.
    onView
(withId(R.id.text_action_bar_result))
       
.check(matches(withText("World")));
}

ओवरफ़्लो मेन्यू बटन दिखाई देता है, और इसके नीचे एक सूची
          कार्रवाई बार, जो स्क्रीन के ऊपरी हिस्से के पास मौजूद है

हार्डवेयर ओवरफ़्लो मेन्यू बटन वाले डिवाइसों पर यह इस तरह दिखता है:

कोई ओवरफ़्लो मेन्यू बटन नहीं होता है और सबसे नीचे एक सूची दिखती है
          स्क्रीन का

संदर्भ के हिसाब से कार्रवाई बार के लिए, ये काम करना आसान हो गया है:

KotlinJava
fun testActionModeOverflow() {
   
// Show the contextual action bar.
    onView
(withId(R.id.show_contextual_action_bar))
       
.perform(click())

   
// Open the overflow menu from contextual action mode.
    openContextualActionModeOverflowMenu
()

   
// Click on the item.
    onView
(withText("Key"))
       
.perform(click())

   
// Verify that we have really clicked on the icon by
   
// checking the TextView content.
    onView
(withId(R.id.text_action_bar_result))
       
.check(matches(withText("Key")))
   
}
}
public void testActionModeOverflow() {
   
// Show the contextual action bar.
    onView
(withId(R.id.show_contextual_action_bar))
       
.perform(click());

   
// Open the overflow menu from contextual action mode.
    openContextualActionModeOverflowMenu
();

   
// Click on the item.
    onView
(withText("Key"))
       
.perform(click());

   
// Verify that we have really clicked on the icon by
   
// checking the TextView content.
    onView
(withId(R.id.text_action_bar_result))
       
.check(matches(withText("Key")));
   
}
}

ओवरफ़्लो मेनू बटन कार्रवाई बार में दिखाई देता है, और
          विकल्प, ऐक्शन बार के नीचे, स्क्रीन में सबसे ऊपर दिखते हैं

इन सैंपल का पूरा कोड देखने के लिए, GitHub पर ActionBarTest.java सैंपल.

दावा करें कि व्यू नहीं दिख रहा है

कार्रवाइयां करने के बाद, आपको की जांच की जा रही है. कभी-कभी, यह एक नकारात्मक मामला हो सकता है, जैसे कि कुछ नहीं हो रहा है. ध्यान रखें कि आप किसी भी हैमक्रेस्ट व्यू को पलट सकते हैं ViewAssertions.matches() का इस्तेमाल करके ViewAssertion में 'मैचर' जोड़ा है.

नीचे दिए गए उदाहरण में, हम isDisplayed() मैचर को लेते हैं और इसका इस्तेमाल करके इसे उलट देते हैं स्टैंडर्ड not() मैचर:

KotlinJava
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import org.hamcrest.Matchers.not

onView
(withId(R.id.bottom_left))
   
.check(matches(not(isDisplayed())))
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static org.hamcrest.Matchers.not;

onView
(withId(R.id.bottom_left))
   
.check(matches(not(isDisplayed())));

ऊपर दिया गया तरीका तब काम करता है, जब व्यू अब भी क्रम में हो. अगर ऐसा है नहीं, तो आपको एक NoMatchingViewException मिलेगा और आपको ViewAssertions.doesNotExist().

दावा करें कि व्यू मौजूद नहीं है

अगर व्यू, व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) से हट गया है, तो ऐसा तब हो सकता है, जब कार्रवाई की वजह से अन्य गतिविधि में बदलाव हुआ—आपको इसका इस्तेमाल करना चाहिए ViewAssertions.doesNotExist():

KotlinJava
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
import androidx.test.espresso.matcher.ViewMatchers.withId

onView
(withId(R.id.bottom_left))
   
.check(doesNotExist())
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
import static androidx.test.espresso.matcher.ViewMatchers.withId;

onView
(withId(R.id.bottom_left))
   
.check(doesNotExist());

पुष्टि करें कि डेटा आइटम, अडैप्टर में नहीं है

यह साबित करने के लिए कि कोई खास डेटा आइटम, AdapterView में मौजूद नहीं है, आपको ऐसा करना होगा चीज़ों को थोड़ा अलग तरीके से. हमें जिस AdapterView में दिलचस्पी है उसे ढूंढना होगा उसके होल्डिंग डेटा को खोजें और उसके बारे में पूछताछ करें. हमें onData() का इस्तेमाल करने की ज़रूरत नहीं है. इसके बजाय, हम AdapterView को ढूंढने के लिए onView() का इस्तेमाल करते हैं. इसके बाद, हम दूसरा मैचर की सुविधा का इस्तेमाल करके व्यू के अंदर के डेटा पर काम कर सकते हैं.

पहला मैचर:

KotlinJava
private fun withAdaptedData(dataMatcher: Matcher<Any>): Matcher<View> {
   
return object : TypeSafeMatcher<View>() {

       
override fun describeTo(description: Description) {
            description
.appendText("with class name: ")
            dataMatcher
.describeTo(description)
       
}

       
public override fun matchesSafely(view: View) : Boolean {
           
if (view !is AdapterView<*>) {
               
return false
           
}

           
val adapter = view.adapter
           
for (i in 0 until adapter.count) {
               
if (dataMatcher.matches(adapter.getItem(i))) {
                   
return true
               
}
           
}

           
return false
       
}
   
}
}
private static Matcher<View> withAdaptedData(final Matcher<Object> dataMatcher) {
   
return new TypeSafeMatcher<View>() {

       
@Override
       
public void describeTo(Description description) {
            description
.appendText("with class name: ");
            dataMatcher
.describeTo(description);
       
}

       
@Override
       
public boolean matchesSafely(View view) {
           
if (!(view instanceof AdapterView)) {
               
return false;
           
}

           
@SuppressWarnings("rawtypes")
           
Adapter adapter = ((AdapterView) view).getAdapter();
           
for (int i = 0; i < adapter.getCount(); i++) {
               
if (dataMatcher.matches(adapter.getItem(i))) {
                   
return true;
               
}
           
}

           
return false;
       
}
   
};
}

इसके बाद, AdapterView को ढूंढने के लिए हमें बस onView() की ज़रूरत है:

KotlinJava
fun testDataItemNotInAdapter() {
    onView
(withId(R.id.list))
         
.check(matches(not(withAdaptedData(withItemContent("item: 168")))))
   
}
}
@SuppressWarnings("unchecked")
public void testDataItemNotInAdapter() {
    onView
(withId(R.id.list))
         
.check(matches(not(withAdaptedData(withItemContent("item: 168")))));
   
}
}

और हमारा एक दावा है, जो "आइटम: 168" के बराबर वाले आइटम पर लागू नहीं होगा यह आईडी सूची के साथ अडैप्टर व्यू में मौजूद होता है.

पूरा सैंपल देखने के लिए, यहां दिए गए सैंपल में testDataItemNotInAdapter() तरीका देखें AdapterViewTest.java GitHub पर क्लास.

कस्टम फ़ेलियर हैंडलर का इस्तेमाल करें

Espresso में डिफ़ॉल्ट FailureHandler को अपनी पसंद के मुताबिक सेट करने के बाद, यह अनुमति मिल जाती है अन्य या अलग-अलग तरह की गड़बड़ियों को ठीक करना, जैसे कि स्क्रीनशॉट लेना या पास करना साथ ही, डीबग करने की ज़्यादा जानकारी दे सकते हैं.

CustomFailureHandlerTest के उदाहरण में, कस्टम पैरामीटर को लागू करने का तरीका बताया गया है फ़ेलियर हैंडलर:

KotlinJava
private class CustomFailureHandler(targetContext: Context) : FailureHandler {
   
private val delegate: FailureHandler

   
init {
        delegate
= DefaultFailureHandler(targetContext)
   
}

   
override fun handle(error: Throwable, viewMatcher: Matcher<View>) {
       
try {
            delegate
.handle(error, viewMatcher)
       
} catch (e: NoMatchingViewException) {
           
throw MySpecialException(e)
       
}

   
}
}
private static class CustomFailureHandler implements FailureHandler {
   
private final FailureHandler delegate;

   
public CustomFailureHandler(Context targetContext) {
        delegate
= new DefaultFailureHandler(targetContext);
   
}

   
@Override
   
public void handle(Throwable error, Matcher<View> viewMatcher) {
       
try {
            delegate
.handle(error, viewMatcher);
       
} catch (NoMatchingViewException e) {
           
throw new MySpecialException(e);
       
}
   
}
}

यह फ़ेलियर हैंडलर के बजाय MySpecialException NoMatchingViewException और अन्य सभी विफलताओं को डेलिगेट करता है DefaultFailureHandler. CustomFailureHandler को इनसे रजिस्टर किया जा सकता है टेस्ट के setUp() तरीके में एस्प्रेसो:

KotlinJava
@Throws(Exception::class)
override fun setUp() {
   
super.setUp()
    getActivity
()
    setFailureHandler
(CustomFailureHandler(
           
ApplicationProvider.getApplicationContext<Context>()))
}
@Override
public void setUp() throws Exception {
   
super.setUp();
    getActivity
();
    setFailureHandler
(new CustomFailureHandler(
           
ApplicationProvider.getApplicationContext()));
}

ज़्यादा जानकारी के लिए, देखें FailureHandler इंटरफ़ेस और Espresso.setFailureHandler().

उन विंडो को टारगेट करें जो डिफ़ॉल्ट के तौर पर सेट नहीं हैं

Android में कई विंडो काम करती हैं. आम तौर पर, यह जानकारी उपयोगकर्ताओं को दी जाती है और फिर भी कुछ मामलों में कई विंडो दिखती हैं, जैसे कि जैसे कि जब आपके इनबॉक्स में एक ऑटो-कंपलीट विंडो मुख्य ऐप्लिकेशन विंडो पर खींची जाती है खोज विजेट. चीज़ों को आसान बनाने के लिए, Espresso डिफ़ॉल्ट रूप से बताएं कि आपको किस Window से इंटरैक्ट करना है. यह अनुमान करीब-करीब हमेशा अच्छा होता है; हालांकि, बहुत कम मामलों में आपको यह बताना होगा कि को किसी इंटरैक्शन को लक्षित करना चाहिए. ऐसा करने के लिए, अपनी रूट विंडो उपलब्ध कराई जा सकती है मैचर या Root मैचर:

KotlinJava
onView(withText("South China Sea"))
   
.inRoot(withDecorView(not(`is`(getActivity().getWindow().getDecorView()))))
   
.perform(click())
onView(withText("South China Sea"))
   
.inRoot(withDecorView(not(is(getActivity().getWindow().getDecorView()))))
   
.perform(click());

जैसा कि यहां पर किया जा रहा है ViewMatchers, हम पहले से दिया हुआ एक सेट उपलब्ध कराते हैं RootMatchers. बेशक, आप जब चाहें अपना Matcher ऑब्जेक्ट लागू कर सकते हैं.

MultipleWindowTest पर एक नज़र डालें सैंपल GitHub पर.

addHeaderView() का इस्तेमाल करके ListViews में हेडर और फ़ुटर जोड़े जाते हैं addFooterView() तरीके. यह पक्का करने के लिए कि Espresso.onData() को किस डेटा ऑब्जेक्ट के बारे में पता है मिलान करने के लिए, पहले से सेट डेटा ऑब्जेक्ट मान को दूसरे पैरामीटर के रूप में पास करना पक्का करें addHeaderView() और addFooterView() के लिए. उदाहरण के लिए:

KotlinJava
const val FOOTER = "FOOTER"
...
val footerView = layoutInflater.inflate(R.layout.list_item, listView, false)
footerView
.findViewById<TextView>(R.id.item_content).text = "count:"
footerView
.findViewById<TextView>(R.id.item_size).text
       
= data.size.toString
listView
.addFooterView(footerView, FOOTER, true)
public static final String FOOTER = "FOOTER";
...
View footerView = layoutInflater.inflate(R.layout.list_item, listView, false);
footerView
.findViewById<TextView>(R.id.item_content).setText("count:");
footerView
.findViewById<TextView>(R.id.item_size).setText(String.valueOf(data.size()));
listView
.addFooterView(footerView, FOOTER, true);

इसके बाद, फ़ुटर के लिए मैचर लिखा जा सकता है:

KotlinJava
import org.hamcrest.Matchers.allOf
import org.hamcrest.Matchers.instanceOf
import org.hamcrest.Matchers.`is`

fun isFooter(): Matcher<Any> {
   
return allOf(`is`(instanceOf(String::class.java)),
           
`is`(LongListActivity.FOOTER))
}
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;

@SuppressWarnings("unchecked")
public static Matcher<Object> isFooter() {
   
return allOf(is(instanceOf(String.class)), is(LongListActivity.FOOTER));
}

और किसी परीक्षण में दृश्य को लोड करना भी तुंरत है:

KotlinJava
import androidx.test.espresso.Espresso.onData
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.sample.LongListMatchers.isFooter

fun testClickFooter() {
    onData
(isFooter())
       
.perform(click())

   
// ...
}
import static androidx.test.espresso.Espresso.onData;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.sample.LongListMatchers.isFooter;

public void testClickFooter() {
    onData
(isFooter())
       
.perform(click());

   
// ...
}

पूरे कोड सैंपल पर एक नज़र डालें, जो इसकी testClickFooter() तरीके में मिलेगी AdapterViewTest.java GitHub पर.