এসপ্রেসো বেসিক

এসপ্রেসো এপিআই ব্যবহার করে কীভাবে সাধারণ স্বয়ংক্রিয় পরীক্ষার কাজগুলি সম্পূর্ণ করতে হয় এই নথিটি ব্যাখ্যা করে।

এসপ্রেসো এপিআই পরীক্ষার লেখকদের অ্যাপ্লিকেশনের সাথে ইন্টারঅ্যাক্ট করার সময় ব্যবহারকারী কী করতে পারে সে বিষয়ে চিন্তা করতে উত্সাহিত করে - UI উপাদানগুলি সনাক্ত করা এবং তাদের সাথে ইন্টারঅ্যাক্ট করা। একই সময়ে, ফ্রেমওয়ার্ক অ্যাপ্লিকেশানের ক্রিয়াকলাপ এবং দৃশ্যগুলিতে সরাসরি অ্যাক্সেসকে বাধা দেয় কারণ এই বস্তুগুলিকে ধরে রাখা এবং UI থ্রেডের বাইরে সেগুলি পরিচালনা করা পরীক্ষার অস্বচ্ছতার একটি প্রধান উত্স। সুতরাং, আপনি Espresso API-তে getView() এবং getCurrentActivity() এর মত পদ্ধতি দেখতে পাবেন না। আপনি এখনও ViewAction এবং ViewAssertion এর নিজস্ব সাবক্লাস প্রয়োগ করে ভিউতে নিরাপদে কাজ করতে পারেন।

API উপাদান

এসপ্রেসোর প্রধান উপাদানগুলির মধ্যে নিম্নলিখিতগুলি অন্তর্ভুক্ত রয়েছে:

  • এসপ্রেসো – ভিউয়ের সাথে ইন্টারঅ্যাকশনের এন্ট্রি পয়েন্ট ( onView() এবং onData() মাধ্যমে)। এছাড়াও এপিআইগুলিকে প্রকাশ করে যেগুলি অগত্যা কোনও ভিউতে আবদ্ধ নয়, যেমন pressBack()
  • ViewMatchers – বস্তুর একটি সংগ্রহ যা Matcher<? super View> ইন্টারফেস। আপনি বর্তমান ভিউ হায়ারার্কির মধ্যে একটি ভিউ সনাক্ত করতে onView() পদ্ধতিতে এর একটি বা একাধিক পাস করতে পারেন।
  • ViewActionsViewAction অবজেক্টের একটি সংগ্রহ যা ViewInteraction.perform() পদ্ধতিতে পাস করা যেতে পারে, যেমন click()
  • ViewAssertionsViewAssertion বস্তুর একটি সংগ্রহ যা 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() পদ্ধতিটি একটি হ্যামক্রেস্ট ম্যাচার নেয় যা বর্তমান ভিউ হায়ারার্কির মধ্যে একটি — এবং শুধুমাত্র একটি — দেখার আশা করা হয়। ম্যাচার্স শক্তিশালী এবং যারা মকিটো বা জুনিটের সাথে তাদের ব্যবহার করেছে তাদের কাছে পরিচিত হবে। আপনি যদি হ্যামক্রেস্ট ম্যাচারদের সাথে পরিচিত না হন তবে আমরা আপনাকে এই উপস্থাপনাটি দ্রুত দেখে শুরু করার পরামর্শ দিই।

প্রায়শই পছন্দসই ভিউয়ের একটি অনন্য R.id থাকে এবং একটি সাধারণ withId ম্যাচার ভিউ অনুসন্ধানকে সংকুচিত করে। যাইহোক, অনেক বৈধ কেস আছে যখন আপনি পরীক্ষার বিকাশের সময় R.id নির্ধারণ করতে পারবেন না। উদাহরণস্বরূপ, নির্দিষ্ট ভিউতে R.id নাও থাকতে পারে বা R.id অনন্য নয়। এটি সাধারণ ইন্সট্রুমেন্টেশন পরীক্ষাগুলিকে ভঙ্গুর এবং লিখতে জটিল করে তুলতে পারে কারণ ভিউ অ্যাক্সেস করার স্বাভাবিক উপায় — findViewById() — কাজ করে না। এইভাবে, আপনাকে ভিউটি ধরে থাকা কার্যকলাপ বা ফ্র্যাগমেন্টের ব্যক্তিগত সদস্যদের অ্যাক্সেস করতে হবে বা একটি পরিচিত R.id সহ একটি ধারক খুঁজে বের করতে হবে এবং নির্দিষ্ট দৃশ্যের জন্য এর সামগ্রীতে নেভিগেট করতে হবে।

Espresso এই সমস্যাটি পরিষ্কারভাবে পরিচালনা করে যে আপনি বিদ্যমান ViewMatcher অবজেক্ট বা আপনার নিজস্ব কাস্টম ব্যবহার করে দৃশ্যটি সংকুচিত করতে পারবেন।

এর R.id দ্বারা একটি ভিউ খোঁজা onView() কল করার মতোই সহজ:

কোটলিন

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!" লেখা আছে। . আপনি কম্বিনেশন ম্যাচার্স ব্যবহার করে আপনার অনুসন্ধানকে সংকুচিত করতে এটি ব্যবহার করতে পারেন:

কোটলিন

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(click())

জাভা

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

আপনি একটি পারফর্ম কল দিয়ে একাধিক ক্রিয়া সম্পাদন করতে পারেন:

কোটলিন

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

জাভা

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

আপনি যে ভিউটির সাথে কাজ করছেন সেটি যদি একটি ScrollView (উল্লম্ব বা অনুভূমিক) এর ভিতরে অবস্থিত থাকে, তাহলে পূর্ববর্তী ক্রিয়াগুলি বিবেচনা করুন যাতে ভিউটি প্রদর্শন করা প্রয়োজন—যেমন click() এবং typeText() —scrollTo scrollTo() সহ। এটি নিশ্চিত করে যে অন্য ক্রিয়ায় এগিয়ে যাওয়ার আগে দৃশ্যটি প্রদর্শিত হবে:

কোটলিন

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

জাভা

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

এসপ্রেসো দ্বারা প্রদত্ত ভিউ অ্যাকশনের জন্য ViewActions দেখুন।

দেখুন দাবী পরীক্ষা করুন

check() পদ্ধতির মাধ্যমে বর্তমানে নির্বাচিত ভিউতে দাবী প্রয়োগ করা যেতে পারে। সবচেয়ে বেশি ব্যবহৃত দাবী হল matches() assertion। এটি বর্তমানে নির্বাচিত দৃশ্যের অবস্থা জাহির করতে একটি 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!" .

এসপ্রেসো দিয়ে এটি কীভাবে পরীক্ষা করবেন তা এখানে:

বোতামে ক্লিক করুন

প্রথম ধাপ হল এমন একটি সম্পত্তির সন্ধান করা যা বোতামটি খুঁজে পেতে সহায়তা করে। SimpleActivity এর বোতামটিতে একটি অনন্য R.id আছে, যেমনটি প্রত্যাশিত।

কোটলিন

onView(withId(R.id.button_simple))

জাভা

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

এখন ক্লিক করার জন্য:

কোটলিন

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))

জাভা

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

এখন বিষয়বস্তু পাঠ্য যাচাই করতে:

কোটলিন

onView(withId(R.id.text_simple)).check(matches(withText("Hello Espresso!")))

জাভা

onView(withId(R.id.text_simple)).check(matches(withText("Hello Espresso!")));

অ্যাডাপ্টার ভিউতে ডেটা লোড হচ্ছে কিনা দেখুন

AdapterView হল একটি বিশেষ ধরনের উইজেট যা একটি অ্যাডাপ্টার থেকে তার ডেটা গতিশীলভাবে লোড করে। AdapterView -এর সবচেয়ে সাধারণ উদাহরণ হল ListViewLinearLayout এর মতো স্ট্যাটিক উইজেটগুলির বিপরীতে, AdapterView বাচ্চাদের শুধুমাত্র একটি উপসেট বর্তমান ভিউ অনুক্রমের মধ্যে লোড করা যেতে পারে। একটি সাধারণ onView() অনুসন্ধান এমন ভিউ খুঁজে পাবে না যা বর্তমানে লোড করা হয়নি।

এসপ্রেসো একটি পৃথক onData() এন্ট্রি পয়েন্ট প্রদান করে এটি পরিচালনা করে যা প্রথমে প্রশ্নে থাকা অ্যাডাপ্টার আইটেমটিকে লোড করতে সক্ষম হয়, এটিকে বা তার সন্তানদের কোনটি পরিচালনা করার আগে এটিকে ফোকাসে নিয়ে আসে।

সতর্কতা: AdapterView এর কাস্টম বাস্তবায়নের onData() পদ্ধতিতে সমস্যা হতে পারে যদি তারা উত্তরাধিকার চুক্তি, বিশেষ করে getItem() API ভঙ্গ করে। এই ধরনের ক্ষেত্রে, কর্মের সর্বোত্তম পদ্ধতি হল আপনার অ্যাপ্লিকেশন কোড রিফ্যাক্টর করা। আপনি যদি তা করতে না পারেন, তাহলে আপনি একটি মিলে যাওয়া কাস্টম AdapterViewProtocol বাস্তবায়ন করতে পারেন। আরও তথ্যের জন্য, Espresso দ্বারা প্রদত্ত ডিফল্ট AdapterViewProtocols ক্লাস দেখুন।

অ্যাডাপ্টার ভিউ সহজ পরীক্ষা

এই সহজ পরীক্ষাটি দেখায় কিভাবে onData() ব্যবহার করতে হয়। SimpleActivity কয়েকটি আইটেম সহ একটি Spinner রয়েছে যা কফি পানীয়ের ধরণের প্রতিনিধিত্ব করে। যখন একটি আইটেম নির্বাচন করা হয়, সেখানে একটি TextView থাকে যা "One %sa 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 দরকারী ডিবাগিং তথ্য প্রদান করে:

লগিং

এসপ্রেসো লগক্যাটে সমস্ত ভিউ অ্যাকশন লগ করে। যেমন:

ViewInteraction: Performing 'single click' action on view with text: Espresso

অনুক্রম দেখুন

onView() ব্যর্থ হলে Espresso ব্যতিক্রম বার্তায় ভিউ হায়ারার্কি প্রিন্ট করে।

  • যদি 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 স্টুডিওতে হায়ারার্কি ভিউয়ার ব্যবহার করা সর্বদা সহায়ক।

অ্যাডাপ্টার ভিউ সতর্কতা

এসপ্রেসো AdapterView উইজেটের উপস্থিতি সম্পর্কে ব্যবহারকারীদের সতর্ক করে। যখন একটি onView() অপারেশন একটি NoMatchingViewException থ্রো করে এবং AdapterView উইজেটগুলি ভিউ হায়ারার্কিতে উপস্থিত থাকে, তখন সবচেয়ে সাধারণ সমাধান হল onData() ব্যবহার করা। ব্যতিক্রম বার্তাটিতে অ্যাডাপ্টারের ভিউগুলির একটি তালিকা সহ একটি সতর্কতা অন্তর্ভুক্ত থাকবে। আপনি টার্গেট ভিউ লোড করতে onData() আহ্বান করতে এই তথ্য ব্যবহার করতে পারেন।

অতিরিক্ত সম্পদ

অ্যান্ড্রয়েড পরীক্ষায় এসপ্রেসো ব্যবহার সম্পর্কে আরও তথ্যের জন্য, নিম্নলিখিত সংস্থানগুলি দেখুন৷

নমুনা

  • CustomMatcherSample : একটি EditText অবজেক্টের ইঙ্গিত বৈশিষ্ট্যের সাথে মেলে কিভাবে Espresso প্রসারিত করতে হয় তা দেখায়।
  • RecyclerViewSample : Espresso এর জন্য RecyclerView অ্যাকশন।
  • (আরো...)