Espresso-র নিষ্ক্রিয় রিসোর্স

নিষ্ক্রিয় রিসোর্স বলতে এমন একটি অ্যাসিঙ্ক্রোনাস অপারেশনকে বোঝায় যার ফলাফল UI টেস্টে পরবর্তী অপারেশনকে প্রভাবিত করে। Espresso-এর সাথে নিষ্ক্রিয় রিসোর্স রেজিস্টার করার মাধ্যমে, আপনার অ্যাপ পরীক্ষা করার সময় আপনি আরও নির্ভরযোগ্যভাবে এইসব অ্যাসিঙ্ক্রোনাস অপারেশন যাচাই করতে পারবেন।

নিষ্ক্রিয় রিসোর্স কখন প্রয়োজন তা শনাক্ত করা

Espresso-তে সিঙ্ক করার ক্ষমতার একটি অত্যাধুনিক সেট রয়েছে। তবে, ফ্রেমওয়ার্কের এই বৈশিষ্ট্য শুধুমাত্র সেইসব অপারেশনের ক্ষেত্রে প্রযোজ্য হয় যেগুলি MessageQueue-এ মেসেজ পোস্ট করে, যেমন View-এর সাবক্লাস যা স্ক্রিনে এর কন্টেন্ট ড্র করছে।

Espresso ব্যাকগ্রাউন্ড থ্রেডে চলা অপারেশন সহ অন্য কোনও অ্যাসিঙ্ক্রোনাস অপারেশন সম্পর্কে জানে না, তাই Espresso সেইসব পরিস্থিতিতে সিঙ্ক্রোনাইজেশনের গ্যারান্টি দিতে পারে না। Espresso-কে আপনার অ্যাপের দীর্ঘ সময় ধরে চলা অপারেশন সম্পর্কে জানাতে, আপনাকে প্রতিটি অপারেশনকে নিষ্ক্রিয় রিসোর্স হিসেবে রেজিস্টার করতে হবে।

আপনার অ্যাপের অ্যাসিঙ্ক্রোনাস কাজের ফলাফল পরীক্ষা করার সময় আপনি যদি নিষ্ক্রিয় রিসোর্স ব্যবহার না করেন, তাহলে আপনার পরীক্ষার নির্ভরযোগ্যতা উন্নত করার জন্য আপনাকে নিম্নলিখিত খারাপ সমাধানগুলির মধ্যে একটি ব্যবহার করতে হতে পারে:

  • Thread.sleep()-এ কল যোগ করা হচ্ছে। আপনি টেস্টে কৃত্রিম বিলম্ব যোগ করলে, টেস্ট স্যুট সম্পূর্ণ হতে বেশি সময় লাগে এবং স্লো ডিভাইসে টেস্ট রান করলে কখনও কখনও টেস্ট ব্যর্থ হতে পারে। এছাড়াও, এই বিলম্বগুলি ভালভাবে স্কেল করে না, কারণ আপনার অ্যাপকে ভবিষ্যতে রিলিজের ক্ষেত্রে আরও বেশি সময়সাপেক্ষ অ্যাসিঙ্ক্রোনাস কাজ করতে হতে পারে।
  • রিট্রাই র‍্যাপার প্রয়োগ করা, যা টাইমআউট না হওয়া পর্যন্ত আপনার অ্যাপ এখনও অ্যাসিঙ্ক্রোনাস কাজ করছে কিনা তা বারবার চেক করার জন্য একটি লুপ ব্যবহার করে। এমনকি আপনি আপনার টেস্টে সর্বাধিক কতবার আবার চেষ্টা করা হবে তা নির্দিষ্ট করলেও, প্রতিটি রি-এক্সিকিউশন সিস্টেম রিসোর্স, বিশেষ করে CPU ব্যবহার করে।
  • CountDownLatch-এর ইনস্ট্যান্স ব্যবহার করা, যা অন্য থ্রেডে নির্দিষ্ট সংখ্যক অপারেশন সম্পূর্ণ না হওয়া পর্যন্ত এক বা একাধিক থ্রেডকে অপেক্ষা করতে দেয়। এইসব অবজেক্টের জন্য আপনাকে টাইমআউটের সময়সীমা নির্দিষ্ট করতে হবে; অন্যথায়, আপনার অ্যাপ অনির্দিষ্টকালের জন্য ব্লক হয়ে যেতে পারে। ল্যাচগুলি আপনার কোডে অপ্রয়োজনীয় জটিলতা যোগ করে, যার ফলে রক্ষণাবেক্ষণ আরও কঠিন হয়ে পড়ে।

Espresso আপনাকে টেস্ট থেকে এইসব অনির্ভরযোগ্য ওয়ার্কঅ্যারাউন্ড সরিয়ে দেওয়ার অনুমতি দেয় এবং পরিবর্তে আপনার অ্যাপের অ্যাসিঙ্ক্রোনাস কাজকে নিষ্ক্রিয় রিসোর্স হিসেবে রেজিস্টার করে।

সাধারণ ব্যবহারিক প্রয়োগ

আপনার টেস্টে নিম্নলিখিত উদাহরণের মতো অপারেশন করার সময়, নিষ্ক্রিয় রিসোর্স ব্যবহার করার কথা বিবেচনা করুন:

  • ইন্টারনেট বা স্থানীয় ডেটা সোর্স থেকে ডেটা লোড করা।
  • ডেটাবেস এবং কলব্যাকের সাথে কানেকশন তৈরি করা।
  • পরিষেবা ম্যানেজ করা, হয় সিস্টেম পরিষেবা ব্যবহার করে অথবা IntentService-এর ইনস্ট্যান্স ব্যবহার করে।
  • জটিল বিজনেস লজিক পারফর্ম করা, যেমন বিটম্যাপ ট্রান্সফর্মেশন।

এইসব অপারেশন যখন আপনার টেস্টের মাধ্যমে যাচাই করা UI আপডেট করে, তখন নিষ্ক্রিয় রিসোর্স রেজিস্টার করা বিশেষভাবে গুরুত্বপূর্ণ।

নিষ্ক্রিয় রিসোর্স প্রয়োগের উদাহরণ

নিচের তালিকায় নিষ্ক্রিয় রিসোর্সের প্রয়োগের কয়েকটি উদাহরণ দেওয়া হল যা আপনি নিজের অ্যাপে ইন্টিগ্রেট করতে পারবেন:

CountingIdlingResource
অ্যাক্টিভ টাস্কের কাউন্টার বজায় রাখে। কাউন্টার শূন্য হলে, সংশ্লিষ্ট রিসোর্সকে আইডল হিসেবে বিবেচনা করা হয়। এই কার্যকারিতা Semaphore-এর সাথে অনেকটা মিলে যায়। অধিকাংশ ক্ষেত্রে, এই প্রয়োগটি পরীক্ষার সময় আপনার অ্যাপের অ্যাসিঙ্ক্রোনাস কাজ ম্যানেজ করার জন্য যথেষ্ট।
UriIdlingResource
CountingIdlingResource-এর মতোই, তবে রিসোর্সকে নিষ্ক্রিয় হিসেবে বিবেচনা করার আগে নির্দিষ্ট সময়সীমার জন্য কাউন্টার শূন্য হতে হবে। এই অতিরিক্ত অপেক্ষার সময় পরপর নেটওয়ার্ক রিকোয়েস্টকে বিবেচনা করে, যেখানে আপনার থ্রেডের কোনও অ্যাপ আগের রিকোয়েস্টের উত্তর পাওয়ার সাথে সাথেই নতুন রিকোয়েস্ট করতে পারে।
IdlingThreadPoolExecutor
ThreadPoolExecutor-এর একটি কাস্টম ইমপ্লিমেন্টেশন যা তৈরি করা থ্রেড পুলের মধ্যে চলমান টাস্কের মোট সংখ্যার ট্র্যাক রাখে। এই ক্লাস CountingIdlingResource ব্যবহার করে অ্যাক্টিভ টাস্কের কাউন্টার বজায় রাখে।
IdlingScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor-এর কাস্টম প্রয়োগ। এটি IdlingThreadPoolExecutor ক্লাসের মতো একই কার্যকারিতা এবং ক্ষমতা প্রদান করে, তবে এটি ভবিষ্যতের জন্য বা পর্যায়ক্রমে চালানোর জন্য শিডিউল করা টাস্কও ট্র্যাক করতে পারে।

আপনার নিজস্ব নিষ্ক্রিয় রিসোর্স তৈরি করা

আপনার অ্যাপের টেস্টে নিষ্ক্রিয় রিসোর্স ব্যবহার করার সময়, আপনাকে কাস্টম রিসোর্স ম্যানেজমেন্ট বা লগিং প্রদান করতে হতে পারে। সেইসব ক্ষেত্রে, আগের বিভাগে তালিকাভুক্ত প্রয়োগ যথেষ্ট নাও হতে পারে। এমন হলে, আপনি এইসব নিষ্ক্রিয় রিসোর্স ইমপ্লিমেন্টেশনের মধ্যে একটি বাড়াতে বা আপনার নিজস্ব তৈরি করতে পারবেন।

আপনি যদি নিজের নিষ্ক্রিয় রিসোর্স ফাংশনালিটি প্রয়োগ করেন, তাহলে নিম্নলিখিত পেশাদার পদ্ধতিগুলি মনে রাখবেন, বিশেষ করে প্রথমটি:

আইডল চেক করার বাইরে আইডল স্ট্যাটাসে ট্রানজিশন ইনভোক করুন।
আপনার অ্যাপ আইডল হয়ে যাওয়ার পরে, isIdleNow()-এর কোনও ইমপ্লিমেন্টেশনের বাইরে onTransitionToIdle() কল করুন। এইভাবে, Espresso কোনও নির্দিষ্ট নিষ্ক্রিয় রিসোর্স নিষ্ক্রিয় কিনা তা নির্ধারণ করার জন্য দ্বিতীয়বার, অপ্রয়োজনীয় চেক করে না।

নিম্নলিখিত কোড স্নিপেট এই সাজেশনটি ব্যাখ্যা করে:

Kotlin

fun isIdle() {
    // DON'T call callback.onTransitionToIdle() here!
}

fun backgroundWorkDone() {
    // Background work finished.
    callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle.

    // Don't do any post-processing work beyond this point. Espresso now
    // considers your app to be idle and moves on to the next test action.
}

জাভা

public void isIdle() {
    // DON'T call callback.onTransitionToIdle() here!
}

public void backgroundWorkDone() {
    // Background work finished.
    callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle.

    // Don't do any post-processing work beyond this point. Espresso now
    // considers your app to be idle and moves on to the next test action.
}
প্রয়োজন হওয়ার আগেই নিষ্ক্রিয় রিসোর্স রেজিস্টার করুন।

নিষ্ক্রিয় রিসোর্সের সাথে যুক্ত সিঙ্ক্রোনাইজেশন সংক্রান্ত সুবিধা শুধুমাত্র তখনই কার্যকর হয় যখন Espresso প্রথমবার সেই রিসোর্সের isIdleNow() পদ্ধতিকে কল করে।

এই প্রপার্টির বেশ কিছু উদাহরণ নিচে দেওয়া হল:

  • আপনি যদি @Before দিয়ে অ্যানোটেট করা পদ্ধতিতে কোনও নিষ্ক্রিয় রিসোর্স রেজিস্টার করেন, তাহলে নিষ্ক্রিয় রিসোর্স প্রতিটি পরীক্ষার প্রথম লাইনে কার্যকর হয়।
  • আপনি কোনও পরীক্ষার মধ্যে নিষ্ক্রিয় রিসোর্স রেজিস্টার করলে, পরবর্তী Espresso-ভিত্তিক অ্যাকশনের সময় নিষ্ক্রিয় রিসোর্স কার্যকর হয়। পরবর্তী অ্যাকশনটি যদি একই টেস্টে থাকে, তাহলেও এই আচরণ ঘটে, যেমনটি নিষ্ক্রিয় রিসোর্স রেজিস্টার করার স্টেটমেন্টে উল্লেখ করা আছে।
নিষ্ক্রিয় রিসোর্স ব্যবহার করা হয়ে গেলে তা অনিবন্ধিত করুন।

সিস্টেম রিসোর্স সংরক্ষণ করতে, নিষ্ক্রিয় রিসোর্স আর প্রয়োজন না হলে যত তাড়াতাড়ি সম্ভব তা অনিবন্ধিত করুন। যেমন, আপনি যদি @Before দিয়ে অ্যানোটেট করা কোনও পদ্ধতিতে নিষ্ক্রিয় রিসোর্স রেজিস্টার করেন, তাহলে @After দিয়ে অ্যানোটেট করা সংশ্লিষ্ট পদ্ধতিতে এই রিসোর্স আনরেজিস্টার করা সবচেয়ে ভালো।

নিষ্ক্রিয় রিসোর্স রেজিস্টার ও আনরেজিস্টার করতে নিষ্ক্রিয় রেজিস্ট্রি ব্যবহার করুন।

আপনার অ্যাপের নিষ্ক্রিয় রিসোর্সের জন্য এই কন্টেনার ব্যবহার করে, আপনি প্রয়োজন অনুযায়ী বারবার নিষ্ক্রিয় রিসোর্স রেজিস্টার ও আনরেজিস্টার করতে পারবেন এবং তারপরেও একই ধরনের আচরণ দেখতে পাবেন।

নিষ্ক্রিয় রিসোর্সের মধ্যে শুধুমাত্র সহজ অ্যাপ স্টেট বজায় রাখুন।

যেমন, আপনি যে নিষ্ক্রিয় রিসোর্স প্রয়োগ ও রেজিস্টার করেন, তাতে View অবজেক্টের রেফারেন্স থাকা উচিত নয়।

নিষ্ক্রিয় রিসোর্স রেজিস্টার করুন

Espresso একটি কন্টেনার ক্লাস প্রদান করে যেখানে আপনি নিজের অ্যাপের নিষ্ক্রিয় রিসোর্স রাখতে পারবেন। এই ক্লাস, যার নাম IdlingRegistry, হল একটি স্বয়ংসম্পূর্ণ আর্টিফ্যাক্ট যা আপনার অ্যাপে ন্যূনতম ওভারহেড যোগ করে। এই ক্লাস আপনাকে অ্যাপের রক্ষণাবেক্ষণযোগ্যতা উন্নত করার জন্য নিম্নলিখিত পদক্ষেপগুলি নেওয়ার অনুমতি দেয়:

  • আপনার অ্যাপের টেস্টে, নিষ্ক্রিয় রিসোর্সের পরিবর্তে IdlingRegistry-এর একটি রেফারেন্স তৈরি করুন।
  • প্রতিটি বিল্ড ভ্যারিয়েন্টের জন্য আপনি যে নিষ্ক্রিয় রিসোর্সের সংগ্রহ ব্যবহার করেন, সেগুলির মধ্যে পার্থক্য বজায় রাখুন।
  • আপনার অ্যাপের পরিষেবাতে নিষ্ক্রিয় রিসোর্স নির্ধারণ করুন, UI কম্পোনেন্টে নয় যেগুলি সেইসব পরিষেবাকে রেফার করে।

আপনার অ্যাপে নিষ্ক্রিয় রিসোর্স ইন্টিগ্রেট করা

আপনি বিভিন্ন উপায়ে কোনও অ্যাপে নিষ্ক্রিয় রিসোর্স যোগ করতে পারলেও, একটি নির্দিষ্ট পদ্ধতি আপনার অ্যাপের জন্য এনক্যাপসুলেশন বজায় রাখে এবং একই সাথে আপনাকে একটি নির্দিষ্ট অপারেশন উল্লেখ করার অনুমতি দেয় যা একটি প্রদত্ত নিষ্ক্রিয় রিসোর্সকে উপস্থাপন করে।

আপনার অ্যাপে নিষ্ক্রিয় রিসোর্স যোগ করার সময়, আমরা জোরালোভাবে সাজেস্ট করি যে নিষ্ক্রিয় রিসোর্স লজিক অ্যাপেই রাখুন এবং আপনার টেস্টে শুধুমাত্র রেজিস্ট্রেশন ও আনরেজিস্ট্রেশন অপারেশন পারফর্ম করুন।

যদিও আপনি এই পদ্ধতি অনুসরণ করে প্রোডাকশন কোডে শুধুমাত্র টেস্ট-ইন্টারফেস ব্যবহার করার অস্বাভাবিক পরিস্থিতি তৈরি করেন, তবুও আপনি আগে থেকেই থাকা কোডের চারপাশে নিষ্ক্রিয় রিসোর্স র‍্যাপ করতে পারেন, আপনার অ্যাপের APK সাইজ এবং মেথড কাউন্ট বজায় রাখতে পারেন।

বিকল্প পদ্ধতি

আপনার অ্যাপের প্রোডাকশন কোডে নিষ্ক্রিয় রিসোর্স লজিক না রাখতে চাইলে, অন্যান্য অনেক কার্যকর ইন্টিগ্রেশন স্ট্র্যাটেজি আছে:

  • Gradle-এর প্রোডাক্ট ফ্লেভার-এর মতো বিল্ড ভ্যারিয়েন্ট তৈরি করুন এবং শুধুমাত্র আপনার অ্যাপের ডিবাগ বিল্ডে নিষ্ক্রিয় রিসোর্স ব্যবহার করুন।
  • আপনার টেস্টে অ্যাপের নিষ্ক্রিয় রিসোর্স ডিপেন্ডেন্সি গ্রাফ ইনজেক্ট করতে Dagger-এর মতো ডিপেন্ডেন্সি ইনজেকশন ফ্রেমওয়ার্ক ব্যবহার করুন। আপনি Dagger 2 ব্যবহার করলে, ইনজেকশনটি কোনও সাবকম্পোনেন্ট থেকে শুরু হওয়া উচিত।
  • আপনার অ্যাপের টেস্টে একটি নিষ্ক্রিয় রিসোর্স প্রয়োগ করুন এবং আপনার অ্যাপের প্রয়োগের সেই অংশটি প্রকাশ করুন যা সেই টেস্টে সিঙ্ক করতে হবে।

    সতর্কতা: যদিও এই ডিজাইন সংক্রান্ত সিদ্ধান্ত নিষ্ক্রিয় রিসোর্সের জন্য একটি স্বয়ংসম্পূর্ণ রেফারেন্স তৈরি করে বলে মনে হয়, এটি সবচেয়ে সহজ অ্যাপ ছাড়া বাকি সব অ্যাপে এনক্যাপসুলেশন ভেঙে দেয়।

অতিরিক্ত রিসোর্স

Android টেস্টে Espresso ব্যবহার করার ব্যাপারে আরও তথ্য পেতে, নিম্নলিখিত রিসোর্স দেখুন।

নমুনা

  • IdlingResourceSample: ব্যাকগ্রাউন্ডে চলা কাজের সাথে সিঙ্ক্রোনাইজেশন।