এই ডকুমেন্ট থেকে আপনি জানতে পারবেন যে কীভাবে বিভিন্ন ধরনের সাধারণ Espresso টেস্ট সেট-আপ করতে হয়।
একটি ভিউয়ের পাশে আরেকটি ভিউ ম্যাচ করতে
একটি লেআউটে নির্দিষ্ট কিছু ভিউ থাকতে পারে যা স্বতন্ত্র নয়। যেমন,
পরিচিতির সারণীতে বারবার দেখানো কল বোতামের একই
R.id থাকতে পারে, একই টেক্সট থাকতে পারে এবং ভিউ হায়ারার্কিতে অন্যান্য কল বোতামের
মতো একই প্রপার্টি থাকতে পারে।
যেমন, এই অ্যাক্টিভিটিতে, "7" টেক্সট সহ ভিউ একাধিক সারি জুড়ে
রিপিট হয়:

প্রায়ই, অনন্য নয় এমন ভিউকে অনন্য লেবেলের সাথে পেয়ার করা হয় যা এটির পাশে
অবস্থিত, যেমন কল বোতামের পাশে পরিচিতির নাম। এই ক্ষেত্রে,
আপনার বেছে নেওয়া বিকল্প আরও নির্দিষ্ট করতে hasSibling() ম্যাচিং টুল ব্যবহার করতে পারেন:
Kotlin
onView(allOf(withText("7"), hasSibling(withText("item: 0")))) .perform(click())
জাভা
onView(allOf(withText("7"), hasSibling(withText("item: 0")))) .perform(click());
অ্যাকশন বারের মধ্যে থাকা কোনও ভিউয়ের সাথে ম্যাচ করুন
ActionBarTestActivity-এ দুটি আলাদা অ্যাকশন বার আছে: একটি সাধারণ
অ্যাকশন বার এবং একটি প্রাসঙ্গিক অ্যাকশন বার যা বিকল্পের মেনু থেকে তৈরি করা হয়। দুটি
অ্যাকশন বারে একটি আইটেম আছে যা সবসময় দেখা যায় এবং দুটি আইটেম আছে যা শুধুমাত্র
ওভারফ্লো মেনুতে দেখা যায়। কোনও আইটেমে ক্লিক করা হলে, এটি TextView-কে ক্লিক করা আইটেমের
কন্টেন্টে পরিবর্তন করে।
দুটি অ্যাকশন বারে দৃশ্যমান আইকন মেলানো সহজ, যেমনটি নিম্নলিখিত কোড স্নিপেটে দেখানো হয়েছে:
Kotlin
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"))); }

প্রাসঙ্গিক অ্যাকশন বারের জন্য কোডটি একই রকম দেখায়:
Kotlin
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 আমাদের জন্য সেটা ম্যানেজ করে।
সাধারণ অ্যাকশন বারের জন্য:
Kotlin
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"))); }

হার্ডওয়্যার ওভারফ্লো মেনু বোতাম সহ ডিভাইসে এটি এইভাবে দেখা যায়:

প্রাসঙ্গিক অ্যাকশন বারের জন্য এটি আবার সত্যিই সহজ:
Kotlin
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 স্যাম্পেল দেখুন।
কোনও ভিউ দেখানো হচ্ছে না বলে দাবি করুন
একাধিক অ্যাকশন করার পরে, আপনি অবশ্যই টেস্টের অধীনে UI-এর অবস্থা
নিশ্চিত করতে চাইবেন। কখনও কখনও, এটি একটি নেতিবাচক ঘটনা হতে পারে, যেমন যখন
কিছু ঘটছে না। মনে রাখবেন যে আপনি ViewAssertions.matches() ব্যবহার করে যেকোনও hamcrest ভিউ
ম্যাচারকে ViewAssertion-এ পরিবর্তন করতে পারবেন।
নিচের উদাহরণে, আমরা isDisplayed() ম্যাচিং টুল নিয়েছি এবং স্ট্যান্ডার্ড not() ম্যাচিং টুল ব্যবহার করে
এটি রিভার্স করেছি:
Kotlin
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() ব্যবহার করতে হবে:
Kotlin
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() ব্যবহার করি এবং তারপরে ভিউয়ের মধ্যে ডেটা নিয়ে কাজ করার জন্য অন্য একটি
ম্যাচার ব্যবহার করি।
প্রথমে ম্যাচিং টুল:
Kotlin
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() দরকার:
Kotlin
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"))))); } }
এবং আমাদের কাছে একটি অ্যাসারশন আছে যা ব্যর্থ হবে যদি "item: 168" এর সমান একটি আইটেম আইডি তালিকা সহ একটি অ্যাডাপ্টার ভিউতে বিদ্যমান থাকে।
সম্পূর্ণ স্যাম্পেল দেখতে, GitHub-এ
AdapterViewTest.java
ক্লাসের মধ্যে testDataItemNotInAdapter() পদ্ধতি দেখুন।
কাস্টম ফেলিয়র হ্যান্ডলার ব্যবহার করুন
Espresso-তে ডিফল্ট FailureHandler-এর পরিবর্তে কাস্টম ব্যবহার করলে
অতিরিক্ত বা অন্য ধরনের সমস্যা সমাধান করা যায়, যেমন স্ক্রিনশট নেওয়া বা
অতিরিক্ত ডিবাগ তথ্য পাঠানো।
CustomFailureHandlerTest উদাহরণে দেখানো হয়েছে কীভাবে কাস্টম
ব্যর্থতা হ্যান্ডলার প্রয়োগ করতে হয়:
Kotlin
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); } } }
এই ফেলিওর হ্যান্ডলার NoMatchingViewException-এর পরিবর্তে MySpecialException থ্রো করে এবং অন্য সব ফেলিওর DefaultFailureHandler-এ ডেলিগেট করে। CustomFailureHandler-কে টেস্টের setUp() পদ্ধতিতে Espresso-এর সাথে রেজিস্টার করা যেতে পারে:
Kotlin
@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 ম্যাচার প্রদান করে এটি করতে পারেন:
Kotlin
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 অবজেক্ট প্রয়োগ করতে পারবেন।
GitHub-এ MultipleWindowTest স্যাম্পেল দেখুন।
তালিকা ভিউতে হেডার বা ফুটার ম্যাচ করুন
addHeaderView() এবং
addFooterView() পদ্ধতি ব্যবহার করে ListViews-এ হেডার ও ফুটার যোগ করা হয়। Espresso.onData() যাতে বুঝতে পারে কোন ডেটা অবজেক্ট
ম্যাচ করতে হবে, তার জন্য addHeaderView() ও addFooterView()-এ দ্বিতীয় প্যারামিটার হিসেবে
প্রিসেট ডেটা অবজেক্ট ভ্যালু পাস করতে ভুলবেন না। যেমন:
Kotlin
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);
তারপর, আপনি ফুটারের জন্য একটি ম্যাচিং এক্সপ্রেশন লিখতে পারেন:
Kotlin
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)); }
And loading the view in a test is trivial:
Kotlin
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()); // ... }
GitHub-এ AdapterViewTest.java-এর testClickFooter() পদ্ধতিতে সম্পূর্ণ কোডের স্যাম্পেল দেখুন।