টেস্টিং বেসিক

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

ভূমিকা

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

কম্পিউটারগুলি স্কেলিং এবং অটোমেশনে দুর্দান্ত! তাই বড় এবং ছোট কোম্পানিগুলির বিকাশকারীরা স্বয়ংক্রিয় পরীক্ষাগুলি লিখতে পারে, যা এমন পরীক্ষা যা সফ্টওয়্যার দ্বারা চালিত হয় এবং কোড কাজ করে যাচাই করার জন্য আপনাকে ম্যানুয়ালি অ্যাপটি পরিচালনা করতে হবে না।

কোডল্যাবগুলির এই সিরিজে আপনি যা শিখবেন তা হল কিভাবে একটি বাস্তব-বিশ্বের অ্যাপের জন্য পরীক্ষার একটি সংগ্রহ (একটি টেস্টিং স্যুট হিসাবে পরিচিত) তৈরি করতে হয়।

এই প্রথম কোডল্যাবটি Android-এ পরীক্ষার প্রাথমিক বিষয়গুলিকে কভার করে, আপনি আপনার প্রথম পরীক্ষাগুলি লিখবেন এবং জানবেন কিভাবে LiveData এবং ViewModel s পরীক্ষা করতে হয়৷

আপনি ইতিমধ্যে কি জানা উচিত

আপনার সাথে পরিচিত হওয়া উচিত:

আপনি কি শিখবেন

আপনি নিম্নলিখিত বিষয়গুলি সম্পর্কে শিখবেন:

  • কীভাবে অ্যান্ড্রয়েডে ইউনিট পরীক্ষা লিখবেন এবং চালাবেন
  • টেস্ট ড্রাইভেন ডেভেলপমেন্ট কিভাবে ব্যবহার করবেন
  • যন্ত্রযুক্ত পরীক্ষা এবং স্থানীয় পরীক্ষাগুলি কীভাবে চয়ন করবেন

আপনি নিম্নলিখিত লাইব্রেরি এবং কোড ধারণা সম্পর্কে শিখবেন:

আপনি কি করবেন

  • অ্যান্ড্রয়েডে স্থানীয় এবং যন্ত্রযুক্ত উভয় পরীক্ষা সেট আপ করুন, চালান এবং ব্যাখ্যা করুন৷
  • JUnit4 এবং Hamcrest ব্যবহার করে অ্যান্ড্রয়েডে ইউনিট পরীক্ষা লিখুন।
  • সহজ LiveData এবং ViewModel পরীক্ষা লিখুন।

কোডল্যাবগুলির এই সিরিজে, আপনি TO-DO Notes অ্যাপের সাথে কাজ করবেন৷ অ্যাপটি আপনাকে কাজগুলি সম্পূর্ণ করার জন্য লিখতে দেয় এবং সেগুলি একটি তালিকায় প্রদর্শন করে। তারপরে আপনি সেগুলিকে সম্পূর্ণ বা না হিসাবে চিহ্নিত করতে পারেন, সেগুলি ফিল্টার করতে পারেন বা মুছতে পারেন৷

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

শুরু করতে, কোড ডাউনলোড করুন:

জিপ ডাউনলোড করুন

বিকল্পভাবে, আপনি কোডের জন্য Github সংগ্রহস্থল ক্লোন করতে পারেন:

$ git clone https://github.com/googlecodelabs/android-testing.git
$ cd android-testing
$ git checkout starter_code

এই টাস্কে আপনি অ্যাপটি চালাবেন এবং কোড বেস অন্বেষণ করবেন।

ধাপ 1: নমুনা অ্যাপ চালান

একবার আপনি TO-DO অ্যাপটি ডাউনলোড করলে, এটিকে অ্যান্ড্রয়েড স্টুডিওতে খুলুন এবং চালান। এটা কম্পাইল করা উচিত. নিম্নলিখিতগুলি করে অ্যাপটি অন্বেষণ করুন:

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

ধাপ 2: নমুনা অ্যাপ কোড অন্বেষণ করুন

TO-DO অ্যাপটি জনপ্রিয় আর্কিটেকচার ব্লুপ্রিন্ট টেস্টিং এবং আর্কিটেকচার নমুনা (নমুনার প্রতিক্রিয়াশীল আর্কিটেকচার সংস্করণ ব্যবহার করে) এর উপর ভিত্তি করে তৈরি। অ্যাপটি একটি গাইড থেকে অ্যাপ আর্কিটেকচারের আর্কিটেকচার অনুসরণ করে। এটি ফ্র্যাগমেন্টস, একটি সংগ্রহস্থল এবং রুম সহ ভিউ মডেল ব্যবহার করে। আপনি যদি নীচের যেকোন উদাহরণের সাথে পরিচিত হন তবে এই অ্যাপটির একটি অনুরূপ আর্কিটেকচার রয়েছে:

যেকোন একটি স্তরে যুক্তির গভীর বোঝার চেয়ে অ্যাপটির সাধারণ আর্কিটেকচার বোঝার চেয়ে এটি আরও গুরুত্বপূর্ণ।

এখানে আপনি যে প্যাকেজগুলি পাবেন তার সারাংশ:

প্যাকেজ: com.example.android.architecture.blueprints.todoapp

.addedittask

একটি টাস্ক স্ক্রীন যোগ বা সম্পাদনা করুন: একটি টাস্ক যোগ বা সম্পাদনা করার জন্য UI স্তর কোড।

.data

ডাটা লেয়ার: এটি কাজের ডাটা লেয়ার নিয়ে কাজ করে। এতে ডাটাবেস, নেটওয়ার্ক এবং রিপোজিটরি কোড রয়েছে।

.statistics

পরিসংখ্যান স্ক্রীন: পরিসংখ্যান পর্দার জন্য UI স্তর কোড।

.taskdetail

টাস্ক ডিটেইল স্ক্রিন: একটি টাস্কের জন্য UI লেয়ার কোড।

.tasks

টাস্ক স্ক্রিন: সমস্ত কাজের তালিকার জন্য UI লেয়ার কোড।

.util

ইউটিলিটি ক্লাস: অ্যাপের বিভিন্ন অংশে ব্যবহৃত শেয়ার্ড ক্লাস, যেমন একাধিক স্ক্রিনে ব্যবহৃত সোয়াইপ রিফ্রেশ লেআউটের জন্য।

ডেটা স্তর (.ডেটা)

এই অ্যাপটিতে একটি সিমুলেটেড নেটওয়ার্কিং স্তর রয়েছে, দূরবর্তী প্যাকেজে এবং স্থানীয় প্যাকেজে একটি ডাটাবেস স্তর রয়েছে৷ সরলতার জন্য, এই প্রজেক্টে নেটওয়ার্কিং লেয়ারটি প্রকৃত নেটওয়ার্ক অনুরোধ করার পরিবর্তে বিলম্ব সহ একটি HashMap সাথে সিমুলেট করা হয়েছে।

DefaultTasksRepository নেটওয়ার্কিং স্তর এবং ডাটাবেস স্তরের মধ্যে সমন্বয় বা মধ্যস্থতা করে এবং এটিই UI স্তরে ডেটা ফেরত দেয়।

UI স্তর (.addedittask, .statistics, .taskdetail, .tasks)

প্রতিটি UI স্তর প্যাকেজে একটি খণ্ড এবং একটি ভিউ মডেল রয়েছে, সাথে UI-এর জন্য প্রয়োজনীয় অন্যান্য ক্লাসের সাথে (যেমন টাস্ক তালিকার জন্য একটি অ্যাডাপ্টার)। TaskActivity হল সেই ক্রিয়াকলাপ যাতে সমস্ত অংশ থাকে।

নেভিগেশন

অ্যাপের জন্য নেভিগেশন নেভিগেশন উপাদান দ্বারা নিয়ন্ত্রিত হয়। এটি nav_graph.xml ফাইলে সংজ্ঞায়িত করা হয়েছে। Event ক্লাস ব্যবহার করে ভিউ মডেলগুলিতে নেভিগেশন ট্রিগার করা হয়; ভিউ মডেলগুলিও নির্ধারণ করে যে কোন আর্গুমেন্টগুলি পাস করতে হবে। টুকরোগুলি Event পর্যবেক্ষণ করে এবং পর্দার মধ্যে প্রকৃত নেভিগেশন করে।

এই টাস্কে, আপনি আপনার প্রথম পরীক্ষা চালাবেন।

  1. অ্যান্ড্রয়েড স্টুডিওতে, প্রকল্প ফলক খুলুন এবং এই তিনটি ফোল্ডার খুঁজুন:
  • com.example.android.architecture.blueprints.todoapp
  • com.example.android.architecture.blueprints.todoapp (androidTest)
  • com.example.android.architecture.blueprints.todoapp (test)

এই ফোল্ডারগুলি সোর্স সেট হিসাবে পরিচিত। সোর্স সেট হল আপনার অ্যাপের সোর্স কোড ধারণকারী ফোল্ডার। সোর্স সেটগুলি, যেগুলি রঙিন সবুজ ( androidTest এবং test ) আপনার পরীক্ষাগুলি ধারণ করে৷ আপনি যখন একটি নতুন অ্যান্ড্রয়েড প্রকল্প তৈরি করেন, আপনি ডিফল্টরূপে নিম্নলিখিত তিনটি উৎস সেট পাবেন৷ তারা হল:

  • main : আপনার অ্যাপ কোড রয়েছে। এই কোডটি আপনি তৈরি করতে পারেন এমন অ্যাপের বিভিন্ন সংস্করণের মধ্যে ভাগ করা হয়েছে ( বিল্ড ভেরিয়েন্ট হিসাবে পরিচিত)
  • androidTest : ইন্সট্রুমেন্টেড টেস্ট নামে পরিচিত পরীক্ষা রয়েছে।
  • test : স্থানীয় পরীক্ষা হিসাবে পরিচিত পরীক্ষা রয়েছে।

স্থানীয় পরীক্ষা এবং যন্ত্রযুক্ত পরীক্ষার মধ্যে পার্থক্য হল সেগুলি চালানোর পদ্ধতিতে।

স্থানীয় পরীক্ষা ( test উত্স সেট)

এই পরীক্ষাগুলি স্থানীয়ভাবে আপনার ডেভেলপমেন্ট মেশিনের JVM-এ চালানো হয় এবং কোনো এমুলেটর বা শারীরিক ডিভাইসের প্রয়োজন হয় না। এই কারণে, তারা দ্রুত দৌড়ায়, কিন্তু তাদের বিশ্বস্ততা কম, যার অর্থ তারা বাস্তব জগতের মতো কম কাজ করে।

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

ইন্সট্রুমেন্টেড টেস্ট ( androidTest সোর্স সেট)

এই পরীক্ষাগুলি বাস্তব বা অনুকরণ করা অ্যান্ড্রয়েড ডিভাইসগুলিতে চালিত হয়, তাই তারা বাস্তব জগতে কী ঘটবে তা প্রতিফলিত করে, তবে এটি অনেক ধীর।

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

ধাপ 1: একটি স্থানীয় পরীক্ষা চালান

  1. আপনি ExampleUnitTest.kt ফাইলটি না পাওয়া পর্যন্ত test ফোল্ডারটি খুলুন।
  2. এটিতে ডান-ক্লিক করুন এবং ExampleUnitTest চালান নির্বাচন করুন।

আপনি পর্দার নীচে রান উইন্ডোতে নিম্নলিখিত আউটপুট দেখতে হবে:

  1. সবুজ চেকমার্কগুলি লক্ষ্য করুন এবং addition_isCorrect নামক একটি পরীক্ষা পাস হয়েছে তা নিশ্চিত করতে পরীক্ষার ফলাফলগুলি প্রসারিত করুন। এটা জানা ভাল যে সংযোজন প্রত্যাশিত হিসাবে কাজ করে!

ধাপ 2: পরীক্ষা ব্যর্থ করুন

নীচে আপনি এইমাত্র দৌড়েছেন এমন পরীক্ষা।

ExampleUnitTest.kt

// A test class is just a normal class
class ExampleUnitTest {

   // Each test is annotated with @Test (this is a Junit annotation)
   @Test
   fun addition_isCorrect() {
       // Here you are checking that 4 is the same as 2+2
       assertEquals(4, 2 + 2)
   }
}

পরীক্ষা যে লক্ষ্য করুন

  • পরীক্ষার উত্স সেটগুলির একটিতে একটি ক্লাস।
  • @Test টীকা দিয়ে শুরু হওয়া ফাংশনগুলি রয়েছে (প্রতিটি ফাংশন একটি একক পরীক্ষা)।
  • u8 সাধারণত দাবী বিবৃতি ধারণ করে।

অ্যান্ড্রয়েড পরীক্ষার জন্য পরীক্ষামূলক লাইব্রেরি JUnit ব্যবহার করে (এই কোডল্যাবে JUnit4)। উভয়, দাবী এবং @Test টীকা JUnit থেকে এসেছে।

একটি দাবী আপনার পরীক্ষার মূল. এটি একটি কোড বিবৃতি যা পরীক্ষা করে যে আপনার কোড বা অ্যাপটি প্রত্যাশা অনুযায়ী আচরণ করেছে। এই ক্ষেত্রে, দাবিটি assertEquals(4, 2 + 2) যা পরীক্ষা করে যে 4 2 + 2 এর সমান।

একটি ব্যর্থ পরীক্ষা কেমন দেখায় তা দেখতে একটি দাবী যোগ করুন যা আপনি সহজেই দেখতে পাচ্ছেন ব্যর্থ হওয়া উচিত। এটা চেক করবে যে 3 সমান 1+1।

  1. addition_isCorrect পরীক্ষায় assertEquals(3, 1 + 1) যোগ করুন।

ExampleUnitTest.kt

class ExampleUnitTest {

   // Each test is annotated with @Test (this is a Junit annotation)
   @Test
   fun addition_isCorrect() {
       assertEquals(4, 2 + 2)
       assertEquals(3, 1 + 1) // This should fail
   }
}
  1. পরীক্ষা চালান।
  1. পরীক্ষার ফলাফলে, পরীক্ষার পাশে একটি X লক্ষ্য করুন।

  1. এছাড়াও লক্ষ্য করুন:
  • একটি একক ব্যর্থ দাবি পুরো পরীক্ষায় ব্যর্থ হয়।
  • আপনাকে বলা হয়েছে প্রত্যাশিত মান (3) বনাম যে মানটি আসলে গণনা করা হয়েছিল (2)।
  • আপনাকে ব্যর্থ দাবির লাইনে নির্দেশিত করা হয়েছে (ExampleUnitTest.kt:16)

ধাপ 3: একটি যন্ত্রযুক্ত পরীক্ষা চালান

যন্ত্রযুক্ত পরীক্ষাগুলি androidTest উত্স সেটে রয়েছে৷

  1. androidTest সোর্স সেট খুলুন।
  2. ExampleInstrumentedTest নামক পরীক্ষাটি চালান।

ইন্সট্রুমেন্টেড টেস্টের উদাহরণ

@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
    @Test
    fun useAppContext() {
        // Context of the app under test.
        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
        assertEquals("com.example.android.architecture.blueprints.reactive",
            appContext.packageName)
    }
}

স্থানীয় পরীক্ষার বিপরীতে, এই পরীক্ষাটি একটি ডিভাইসে চলে (একটি অনুকরণ করা Pixel 2 ফোনের নীচের উদাহরণে):

আপনার যদি একটি ডিভাইস সংযুক্ত থাকে বা একটি এমুলেটর চলমান থাকে, তাহলে আপনাকে এমুলেটরে পরীক্ষা চালানো দেখতে হবে।

এই টাস্কে, আপনি getActiveAndCompleteStats এর জন্য পরীক্ষা লিখবেন, যা আপনার অ্যাপের জন্য সক্রিয় এবং সম্পূর্ণ টাস্ক পরিসংখ্যানের শতাংশ গণনা করে। আপনি অ্যাপের পরিসংখ্যান স্ক্রিনে এই সংখ্যাগুলি দেখতে পারেন।

ধাপ 1: একটি পরীক্ষা ক্লাস তৈরি করুন

  1. main উৎস সেটে, todoapp.statistics এ, StatisticsUtils.kt খুলুন।
  2. getActiveAndCompletedStats ফাংশন খুঁজুন।

StatisticsUtils.kt

internal fun getActiveAndCompletedStats(tasks: List<Task>?): StatsResult {

   val totalTasks = tasks!!.size
   val numberOfActiveTasks = tasks.count { it.isActive }
   val activePercent = 100 * numberOfActiveTasks / totalTasks
   val completePercent = 100 * (totalTasks - numberOfActiveTasks) / totalTasks

   return StatsResult(
       activeTasksPercent = activePercent.toFloat(),
       completedTasksPercent = completePercent.toFloat()
   )
  
}

data class StatsResult(val activeTasksPercent: Float, val completedTasksPercent: Float)

getActiveAndCompletedStats ফাংশনটি কাজের একটি তালিকা গ্রহণ করে এবং একটি StatsResult প্রদান করে। StatsResult হল একটি ডেটা ক্লাস যাতে দুটি সংখ্যা থাকে, যেগুলি কাজ শেষ হয়েছে তার শতাংশ এবং সক্রিয় শতাংশ।

অ্যান্ড্রয়েড স্টুডিও আপনাকে এই ফাংশনের জন্য পরীক্ষাগুলি বাস্তবায়ন করতে সহায়তা করে টেস্ট স্টাব তৈরি করতে আপনাকে সরঞ্জাম দেয়৷

  1. getActiveAndCompletedStats রাইট ক্লিক করুন এবং Generate > Test নির্বাচন করুন।

টেস্ট তৈরি করুন ডায়ালগ খোলে:

  1. ক্লাসের নাম পরিবর্তন করুন: StatisticsUtilsTest এ ( StatisticsUtilsKtTest এর পরিবর্তে; পরীক্ষার ক্লাসের নামে KT না থাকাটা একটু ভালো)।
  2. বাকি ডিফল্ট রাখুন। JUnit 4 উপযুক্ত পরীক্ষার লাইব্রেরি। গন্তব্য প্যাকেজটি সঠিক (এটি StatisticsUtils ক্লাসের অবস্থানকে মিরর করে) এবং আপনাকে কোনো চেক বক্স চেক করার দরকার নেই (এটি শুধুমাত্র অতিরিক্ত কোড তৈরি করে, কিন্তু আপনি স্ক্র্যাচ থেকে আপনার পরীক্ষা লিখবেন)।
  3. ঠিক আছে টিপুন

গন্তব্য ডিরেক্টরি নির্বাচন করুন ডায়ালগ খোলে:

আপনি একটি স্থানীয় পরীক্ষা করবেন কারণ আপনার ফাংশন গণিত গণনা করছে এবং কোনও Android নির্দিষ্ট কোড অন্তর্ভুক্ত করবে না। সুতরাং, এটি একটি বাস্তব বা অনুকরণ করা ডিভাইসে চালানোর কোন প্রয়োজন নেই।

  1. test ডিরেক্টরি নির্বাচন করুন ( androidTest নয়) কারণ আপনি স্থানীয় পরীক্ষা লিখবেন।
  2. ওকে ক্লিক করুন।
  3. test/statistics/ -এ তৈরি হওয়া StatisticsUtilsTest ক্লাসটি লক্ষ্য করুন।

ধাপ 2: আপনার প্রথম পরীক্ষা ফাংশন লিখুন

আপনি একটি পরীক্ষা লিখতে যাচ্ছেন যা চেক করে:

  • যদি কোনও সম্পূর্ণ কাজ না থাকে এবং একটি সক্রিয় কাজ না থাকে,
  • যে সক্রিয় পরীক্ষার শতাংশ 100%,
  • এবং সমাপ্ত কাজের শতাংশ হল 0%।
  1. StatisticsUtilsTest খুলুন।
  2. getActiveAndCompletedStats_noCompleted_returnsHundredZero নামে একটি ফাংশন তৈরি করুন।

StatisticsUtilsTest.kt

class StatisticsUtilsTest {

    fun getActiveAndCompletedStats_noCompleted_returnsHundredZero() {
        // Create an active task

        // Call your function

        // Check the result
    }
}
  1. এটি একটি পরীক্ষা নির্দেশ করতে ফাংশনের নামের উপরে @Test টীকা যোগ করুন।
  2. কাজের একটি তালিকা তৈরি করুন।
// Create an active task 
val tasks = listOf<Task>(
            Task("title", "desc", isCompleted = false)
        )
  1. এই কাজের সাথে getActiveAndCompletedStats কল করুন।
// Call your function
val result = getActiveAndCompletedStats(tasks)
  1. দাবী ব্যবহার করে, আপনি যা আশা করেছিলেন result পরীক্ষা করুন।
// Check the result
assertEquals(result.completedTasksPercent, 0f)
assertEquals(result.activeTasksPercent, 100f)

এখানে সম্পূর্ণ কোড আছে.

StatisticsUtilsTest.kt

class StatisticsUtilsTest {

    @Test
    fun getActiveAndCompletedStats_noCompleted_returnsHundredZero() {

        // Create an active task (the false makes this active)
        val tasks = listOf<Task>(
            Task("title", "desc", isCompleted = false)
        )
        // Call your function
        val result = getActiveAndCompletedStats(tasks)

        // Check the result
        assertEquals(result.completedTasksPercent, 0f)
        assertEquals(result.activeTasksPercent, 100f)
    }
}
  1. পরীক্ষা চালান (রাইট ক্লিক করুন StatisticsUtilsTest এবং রান নির্বাচন করুন)।

এটি পাস করা উচিত:

ধাপ 3: হ্যামক্রেস্ট নির্ভরতা যোগ করুন

কারণ আপনার পরীক্ষাগুলি আপনার কোড যা করে তার ডকুমেন্টেশন হিসাবে কাজ করে, সেগুলি মানুষের পাঠযোগ্য হলে এটি চমৎকার। নিম্নলিখিত দুটি দাবী তুলনা করুন:

assertEquals(result.completedTasksPercent, 0f)

// versus

assertThat(result.completedTasksPercent, `is`(0f))

দ্বিতীয় দাবীটি মানুষের বাক্যের মতো অনেক বেশি পড়ে। এটি হ্যামক্রেস্ট নামে একটি দাবী কাঠামো ব্যবহার করে লেখা হয়েছে। পঠনযোগ্য দাবী লেখার আরেকটি ভাল হাতিয়ার হল সত্য গ্রন্থাগার । আপনি দাবী লিখতে এই কোডল্যাবে হ্যামক্রেস্ট ব্যবহার করবেন।

  1. build.grade (Module: app) এবং নিম্নলিখিত নির্ভরতা যোগ করুন।

app/build.gradle

dependencies {
    // Other dependencies
    testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"
}

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

  • implementation —নির্ভরতা পরীক্ষা উত্স সেট সহ সমস্ত উত্স সেটে উপলব্ধ।
  • testImplementation —নির্ভরতা শুধুমাত্র পরীক্ষার উৎস সেটে উপলব্ধ।
  • androidTestImplementation —নির্ভরতা শুধুমাত্র androidTest সোর্স সেটে উপলব্ধ।

আপনি কোন কনফিগারেশন ব্যবহার করেন, যেখানে নির্ভরতা ব্যবহার করা যেতে পারে তা নির্ধারণ করে। আপনি যদি লেখেন:

testImplementation "org.hamcrest:hamcrest-all:$hamcrestVersion"

এর মানে হ্যামক্রেস্ট শুধুমাত্র পরীক্ষার উৎস সেটে পাওয়া যাবে। এটি নিশ্চিত করে যে হ্যামক্রেস্ট আপনার চূড়ান্ত অ্যাপে অন্তর্ভুক্ত হবে না।

ধাপ 4: দাবী লিখতে হ্যামক্রেস্ট ব্যবহার করুন

  1. assertEquals এর পরিবর্তে Hamcrest এর assertThat ব্যবহার করতে getActiveAndCompletedStats_noCompleted_returnsHundredZero() পরীক্ষাটি আপডেট করুন।
// REPLACE
assertEquals(result.completedTasksPercent, 0f)
assertEquals(result.activeTasksPercent, 100f)

// WITH
assertThat(result.activeTasksPercent, `is`(100f))
assertThat(result.completedTasksPercent, `is`(0f))

নোট করুন আপনি ইম্পোর্ট import org.hamcrest.Matchers.`is` ব্যবহার করতে পারেন যদি অনুরোধ করা হয়।

চূড়ান্ত পরীক্ষা নীচের কোড মত দেখাবে.

StatisticsUtilsTest.kt

import com.example.android.architecture.blueprints.todoapp.data.Task
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.`is`
import org.junit.Test

class StatisticsUtilsTest {

    @Test
    fun getActiveAndCompletedStats_noCompleted_returnsHundredZero {

        // Create an active tasks (the false makes this active)
        val tasks = listOf<Task>(
            Task("title", "desc", isCompleted = false)
        )
        // Call your function
        val result = getActiveAndCompletedStats(tasks)

        // Check the result
        assertThat(result.activeTasksPercent, `is`(100f))
        assertThat(result.completedTasksPercent, `is`(0f))

    }
}
  1. এটি এখনও কাজ করে তা নিশ্চিত করতে আপনার আপডেট করা পরীক্ষা চালান!

এই কোডল্যাব আপনাকে হ্যামক্রেস্টের সমস্ত ইনস এবং আউটগুলি শেখাবে না , তাই আপনি যদি আরও শিখতে চান তবে অফিসিয়াল টিউটোরিয়ালটি দেখুন।

এটি অনুশীলনের জন্য একটি ঐচ্ছিক কাজ।

এই টাস্কে, আপনি JUnit এবং Hamcrest ব্যবহার করে আরও পরীক্ষা লিখবেন। আপনি টেস্ট ড্রাইভেন ডেভেলপমেন্টের প্রোগ্রাম অনুশীলন থেকে প্রাপ্ত একটি কৌশল ব্যবহার করে পরীক্ষাও লিখবেন। টেস্ট ড্রাইভেন ডেভেলপমেন্ট বা TDD হল প্রোগ্রামিং চিন্তার একটি স্কুল যা বলে যে আপনার বৈশিষ্ট্য কোড প্রথমে লেখার পরিবর্তে, আপনি প্রথমে আপনার পরীক্ষাগুলি লিখুন। তারপর আপনি আপনার পরীক্ষা পাস করার লক্ষ্য সঙ্গে আপনার বৈশিষ্ট্য কোড লিখুন.

ধাপ 1. পরীক্ষা লিখুন

আপনার যখন একটি স্বাভাবিক কাজের তালিকা থাকবে তার জন্য পরীক্ষা লিখুন:

  1. যদি একটি সম্পূর্ণ টাস্ক থাকে এবং কোন সক্রিয় টাস্ক না থাকে, তাহলে activeTasks শতাংশ 0f হওয়া উচিত এবং সম্পূর্ণ করা টাস্কের শতাংশ 100f হওয়া উচিত।
  2. দুটি সম্পূর্ণ কাজ এবং তিনটি সক্রিয় কাজ থাকলে, সম্পূর্ণ শতাংশ 40f এবং সক্রিয় শতাংশ 60f হওয়া উচিত।

ধাপ 2. একটি বাগ জন্য একটি পরীক্ষা লিখুন

getActiveAndCompletedStats এর কোডে একটি বাগ আছে। তালিকাটি খালি বা শূন্য হলে কী হবে তা কীভাবে সঠিকভাবে পরিচালনা করে না তা লক্ষ্য করুন। এই উভয় ক্ষেত্রে, উভয় শতাংশই শূন্য হওয়া উচিত।

internal fun getActiveAndCompletedStats(tasks: List<Task>?): StatsResult {

   val totalTasks = tasks!!.size
   val numberOfActiveTasks = tasks.count { it.isActive }
   val activePercent = 100 * numberOfActiveTasks / totalTasks
   val completePercent = 100 * (totalTasks - numberOfActiveTasks) / totalTasks

   return StatsResult(
       activeTasksPercent = activePercent.toFloat(),
       completedTasksPercent = completePercent.toFloat()
   )
  
}

কোড ঠিক করতে এবং পরীক্ষা লিখতে, আপনি পরীক্ষা চালিত বিকাশ ব্যবহার করবেন। টেস্ট চালিত বিকাশ এই পদক্ষেপগুলি অনুসরণ করে।

  1. দেওয়া, কখন, তারপর গঠন ব্যবহার করে এবং নিয়ম অনুসরণ করে এমন একটি নাম দিয়ে পরীক্ষাটি লিখুন।
  2. পরীক্ষা ব্যর্থ নিশ্চিত করুন.
  3. পরীক্ষায় উত্তীর্ণ হওয়ার জন্য সর্বনিম্ন কোডটি লিখুন।
  4. সব পরীক্ষার জন্য পুনরাবৃত্তি!

বাগ সংশোধন করে শুরু করার পরিবর্তে, আপনি প্রথমে পরীক্ষা লিখে শুরু করবেন। তারপরে আপনি নিশ্চিত করতে পারেন যে আপনার পরীক্ষাগুলি আপনাকে ভবিষ্যতে ভুলবশত এই বাগগুলি পুনরায় প্রবর্তন করা থেকে রক্ষা করবে৷

  1. যদি একটি খালি তালিকা থাকে ( emptyList() ), তাহলে উভয় শতাংশই 0f হওয়া উচিত।
  2. যদি কাজগুলি লোড করার সময় একটি ত্রুটি থাকে তবে তালিকাটি null হবে এবং উভয় শতাংশই 0f হওয়া উচিত।
  3. আপনার পরীক্ষা চালান এবং নিশ্চিত করুন যে তারা ব্যর্থ হয়েছে :

ধাপ 3. বাগ ঠিক করুন

এখন আপনার পরীক্ষা আছে, বাগ ঠিক করুন।

  1. যদি tasks null বা খালি থাকে তবে 0f ফেরত দিয়ে getActiveAndCompletedStats এ বাগটি ঠিক করুন:
internal fun getActiveAndCompletedStats(tasks: List<Task>?): StatsResult {

    return if (tasks == null || tasks.isEmpty()) {
        StatsResult(0f, 0f)
    } else {
        val totalTasks = tasks.size
        val numberOfActiveTasks = tasks.count { it.isActive }
        StatsResult(
            activeTasksPercent = 100f * numberOfActiveTasks / tasks.size,
            completedTasksPercent = 100f * (totalTasks - numberOfActiveTasks) / tasks.size
        )
    }
}
  1. আবার আপনার পরীক্ষা চালান এবং নিশ্চিত করুন যে সমস্ত পরীক্ষা এখন পাস!

TDD অনুসরণ করে এবং প্রথমে পরীক্ষা লিখে, আপনি নিশ্চিত করতে সাহায্য করেছেন যে:

  • নতুন কার্যকারিতা সবসময় সংশ্লিষ্ট পরীক্ষা আছে; এইভাবে আপনার পরীক্ষাগুলি আপনার কোড যা করে তার ডকুমেন্টেশন হিসাবে কাজ করে।
  • আপনার পরীক্ষাগুলি সঠিক ফলাফলের জন্য পরীক্ষা করে এবং আপনি ইতিমধ্যে দেখেছেন এমন বাগগুলি থেকে রক্ষা করে৷

সমাধান: আরও পরীক্ষা লেখা

এখানে সব পরীক্ষা এবং সংশ্লিষ্ট বৈশিষ্ট্য কোড আছে.

StatisticsUtilsTest.kt

class StatisticsUtilsTest {

    @Test
    fun getActiveAndCompletedStats_noCompleted_returnsHundredZero {
        val tasks = listOf(
            Task("title", "desc", isCompleted = false)
        )
        // When the list of tasks is computed with an active task
        val result = getActiveAndCompletedStats(tasks)

        // Then the percentages are 100 and 0
        assertThat(result.activeTasksPercent, `is`(100f))
        assertThat(result.completedTasksPercent, `is`(0f))
    }

    @Test
    fun getActiveAndCompletedStats_noActive_returnsZeroHundred() {
        val tasks = listOf(
            Task("title", "desc", isCompleted = true)
        )
        // When the list of tasks is computed with a completed task
        val result = getActiveAndCompletedStats(tasks)

        // Then the percentages are 0 and 100
        assertThat(result.activeTasksPercent, `is`(0f))
        assertThat(result.completedTasksPercent, `is`(100f))
    }

    @Test
    fun getActiveAndCompletedStats_both_returnsFortySixty() {
        // Given 3 completed tasks and 2 active tasks
        val tasks = listOf(
            Task("title", "desc", isCompleted = true),
            Task("title", "desc", isCompleted = true),
            Task("title", "desc", isCompleted = true),
            Task("title", "desc", isCompleted = false),
            Task("title", "desc", isCompleted = false)
        )
        // When the list of tasks is computed
        val result = getActiveAndCompletedStats(tasks)

        // Then the result is 40-60
        assertThat(result.activeTasksPercent, `is`(40f))
        assertThat(result.completedTasksPercent, `is`(60f))
    }

    @Test
    fun getActiveAndCompletedStats_error_returnsZeros() {
        // When there's an error loading stats
        val result = getActiveAndCompletedStats(null)

        // Both active and completed tasks are 0
        assertThat(result.activeTasksPercent, `is`(0f))
        assertThat(result.completedTasksPercent, `is`(0f))
    }

    @Test
    fun getActiveAndCompletedStats_empty_returnsZeros() {
        // When there are no tasks
        val result = getActiveAndCompletedStats(emptyList())

        // Both active and completed tasks are 0
        assertThat(result.activeTasksPercent, `is`(0f))
        assertThat(result.completedTasksPercent, `is`(0f))
    }
}

StatisticsUtils.kt

internal fun getActiveAndCompletedStats(tasks: List<Task>?): StatsResult {

    return if (tasks == null || tasks.isEmpty()) {
        StatsResult(0f, 0f)
    } else {
        val totalTasks = tasks.size
        val numberOfActiveTasks = tasks.count { it.isActive }
        StatsResult(
            activeTasksPercent = 100f * numberOfActiveTasks / tasks.size,
            completedTasksPercent = 100f * (totalTasks - numberOfActiveTasks) / tasks.size
        )
    }
}

লেখার এবং চলমান পরীক্ষার মৌলিক বিষয়গুলির সাথে দুর্দান্ত কাজ! এরপরে আপনি শিখবেন কিভাবে মৌলিক ViewModel এবং LiveData পরীক্ষা লিখতে হয়।

কোডল্যাবের বাকি অংশে, আপনি শিখবেন কীভাবে দুটি অ্যান্ড্রয়েড ক্লাসের জন্য পরীক্ষা লিখতে হয় যা বেশিরভাগ অ্যাপ জুড়ে সাধারণ— ViewModel এবং LiveData

আপনি TasksViewModel জন্য পরীক্ষা লিখে শুরু করেন।


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



আপনি যে পরীক্ষাটি লিখবেন তা পরীক্ষা করবে যে আপনি যখন addNewTask পদ্ধতিতে কল করবেন, তখন নতুন টাস্ক উইন্ডো খোলার Event বরখাস্ত হয়েছে। আপনি যে অ্যাপ কোডটি পরীক্ষা করবেন তা এখানে।

TasksViewModel.kt

fun addNewTask() {
   _newTaskEvent.value = Event(Unit)
}

ধাপ 1. একটি TasksViewModelTest ক্লাস তৈরি করুন

আপনি StatisticsUtilTest জন্য একই পদক্ষেপগুলি অনুসরণ করে, এই ধাপে, আপনি TasksViewModelTest জন্য একটি পরীক্ষা ফাইল তৈরি করুন।

  1. আপনি যে ক্লাসটি পরীক্ষা করতে চান সেটি খুলুন, tasks প্যাকেজে, TasksViewModel.
  2. কোডে, ক্লাস নামের TasksViewModel -> Generate -> Test- এ ডান-ক্লিক করুন।

  1. পরীক্ষা তৈরি করুন স্ক্রিনে, গ্রহণ করতে ঠিক আছে ক্লিক করুন (ডিফল্ট সেটিংস পরিবর্তন করার প্রয়োজন নেই)।
  2. গন্তব্য ডিরেক্টরি নির্বাচন করুন ডায়ালগে, পরীক্ষা ডিরেক্টরি নির্বাচন করুন।

ধাপ 2. আপনার ভিউমডেল পরীক্ষা লেখা শুরু করুন

এই ধাপে আপনি একটি ভিউ মডেল টেস্ট যোগ করেন পরীক্ষা করার জন্য যে আপনি যখন addNewTask পদ্ধতিতে কল করেন, তখন নতুন টাস্ক উইন্ডো খোলার Event বরখাস্ত হয়।

  1. addNewTask_setsNewTaskEvent নামে একটি নতুন পরীক্ষা তৈরি করুন।

TasksViewModelTest.kt

class TasksViewModelTest {

    @Test
    fun addNewTask_setsNewTaskEvent() {

        // Given a fresh TasksViewModel


        // When adding a new task


        // Then the new task event is triggered

    }
    
}

আবেদন প্রসঙ্গে কি?

আপনি যখন পরীক্ষা করার জন্য TasksViewModel এর একটি উদাহরণ তৈরি করেন, তখন এর কনস্ট্রাক্টরের একটি অ্যাপ্লিকেশন প্রসঙ্গ প্রয়োজন। কিন্তু এই পরীক্ষায়, আপনি ক্রিয়াকলাপ এবং UI এবং টুকরো দিয়ে একটি সম্পূর্ণ অ্যাপ্লিকেশন তৈরি করছেন না, তাহলে আপনি কীভাবে একটি অ্যাপ্লিকেশন প্রসঙ্গ পাবেন?

TasksViewModelTest.kt

// Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(???)

অ্যান্ড্রয়েডএক্স টেস্ট লাইব্রেরিগুলিতে ক্লাস এবং পদ্ধতিগুলি অন্তর্ভুক্ত থাকে যা আপনাকে অ্যাপ্লিকেশন এবং অ্যাক্টিভিটিগুলির মতো উপাদানগুলির সংস্করণগুলি সরবরাহ করে যা পরীক্ষার জন্য। যখন আপনার একটি স্থানীয় পরীক্ষা থাকে যেখানে আপনার সিমুলেটেড অ্যান্ড্রয়েড ফ্রেমওয়ার্ক ক্লাসের প্রয়োজন হয় (যেমন একটি অ্যাপ্লিকেশন প্রসঙ্গ), সঠিকভাবে AndroidX পরীক্ষা সেট আপ করতে এই পদক্ষেপগুলি অনুসরণ করুন:

  1. AndroidX টেস্ট কোর এবং এক্সট নির্ভরতা যোগ করুন
  2. রোবোলেক্ট্রিক টেস্টিং লাইব্রেরি নির্ভরতা যোগ করুন
  3. AndroidJunit4 টেস্ট রানার দিয়ে ক্লাসটি টীকা করুন
  4. AndroidX টেস্ট কোড লিখুন

আপনি এই পদক্ষেপগুলি সম্পূর্ণ করতে যাচ্ছেন এবং তারপরে বুঝতে পারবেন তারা একসাথে কী করে।

ধাপ 3. গ্রেডেল নির্ভরতা যোগ করুন

  1. আপনার অ্যাপ মডিউলের build.gradle ফাইলে এই নির্ভরতাগুলি অনুলিপি করুন মূল AndroidX টেস্ট কোর এবং ext নির্ভরতা, পাশাপাশি Roboelectric testing নির্ভরতা যোগ করতে।

app/build.gradle

    // AndroidX Test - JVM testing
testImplementation "androidx.test.ext:junit-ktx:$androidXTestExtKotlinRunnerVersion"

    testImplementation "androidx.test:core-ktx:$androidXTestCoreVersion"

 testImplementation "org.robolectric:robolectric:$robolectricVersion"

ধাপ 4. জুনিট টেস্ট রানার যোগ করুন

  1. আপনার পরীক্ষার ক্লাসের উপরে @RunWith(AndroidJUnit4::class) যোগ করুন।

TasksViewModelTest.kt

@RunWith(AndroidJUnit4::class)
class TasksViewModelTest {
    // Test code
}

ধাপ 5. AndroidX পরীক্ষা ব্যবহার করুন

এই মুহুর্তে, আপনি AndroidX টেস্ট লাইব্রেরি ব্যবহার করতে পারেন। এর মধ্যে রয়েছে ApplicationProvider.getApplicationContex t পদ্ধতি, যা একটি অ্যাপ্লিকেশন প্রসঙ্গ পায়।

  1. AndroidX পরীক্ষা লাইব্রেরি থেকে ApplicationProvider.getApplicationContext() ব্যবহার করে একটি TasksViewModel তৈরি করুন।

TasksViewModelTest.kt

// Given a fresh ViewModel
val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
  1. tasksViewModeladdNewTask কল করুন।

TasksViewModelTest.kt

tasksViewModel.addNewTask()

এই মুহুর্তে আপনার পরীক্ষাটি নীচের কোডের মতো হওয়া উচিত।

TasksViewModelTest.kt

    @Test
    fun addNewTask_setsNewTaskEvent() {

        // Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

        // When adding a new task
        tasksViewModel.addNewTask()

        // Then the new task event is triggered
        // TODO test LiveData
    }
  1. এটি কাজ করে তা নিশ্চিত করতে আপনার পরীক্ষা চালান

ধারণা: AndroidX পরীক্ষা কিভাবে কাজ করে?

AndroidX পরীক্ষা কি?

AndroidX টেস্ট পরীক্ষার জন্য লাইব্রেরির একটি সংগ্রহ। এটিতে ক্লাস এবং পদ্ধতিগুলি রয়েছে যা আপনাকে অ্যাপ্লিকেশন এবং ক্রিয়াকলাপগুলির মতো উপাদানগুলির সংস্করণ দেয়, যা পরীক্ষার জন্য তৈরি। একটি উদাহরণ হিসাবে, আপনার লেখা এই কোডটি একটি অ্যাপ্লিকেশন প্রসঙ্গ পাওয়ার জন্য একটি AndroidX টেস্ট ফাংশনের একটি উদাহরণ৷

ApplicationProvider.getApplicationContext()

অ্যান্ড্রয়েডএক্স টেস্ট এপিআইগুলির একটি সুবিধা হল যে এগুলি স্থানীয় পরীক্ষা এবং যন্ত্রযুক্ত পরীক্ষার জন্য কাজ করার জন্য তৈরি করা হয়েছে। এটি চমৎকার কারণ:

  • আপনি স্থানীয় পরীক্ষা বা যন্ত্রযুক্ত পরীক্ষা হিসাবে একই পরীক্ষা চালাতে পারেন।
  • স্থানীয় বনাম ইন্সট্রুমেন্টেড পরীক্ষার জন্য আপনাকে বিভিন্ন টেস্টিং API শিখতে হবে না।

উদাহরণস্বরূপ, যেহেতু আপনি AndroidX টেস্ট লাইব্রেরি ব্যবহার করে আপনার কোড লিখেছেন, আপনি আপনার TasksViewModelTest ক্লাসটিকে test ফোল্ডার থেকে androidTest ফোল্ডারে সরাতে পারেন এবং পরীক্ষাগুলি এখনও চলবে৷ getApplicationContext() এটি স্থানীয় বা যন্ত্রযুক্ত পরীক্ষা হিসাবে চালানো হচ্ছে কিনা তার উপর নির্ভর করে কিছুটা ভিন্নভাবে কাজ করে:

  • যদি এটি একটি ইন্সট্রুমেন্টেড পরীক্ষা হয়, এটি একটি এমুলেটর বুট করার সময় বা একটি বাস্তব ডিভাইসের সাথে সংযোগ করার সময় প্রদান করা প্রকৃত অ্যাপ্লিকেশন প্রসঙ্গ পাবে।
  • এটি একটি স্থানীয় পরীক্ষা হলে, এটি একটি সিমুলেটেড অ্যান্ড্রয়েড পরিবেশ ব্যবহার করে।

Roboelectric কি?

স্থানীয় পরীক্ষার জন্য AndroidX টেস্ট যে সিমুলেটেড অ্যান্ড্রয়েড পরিবেশ ব্যবহার করে তা রোবোলেক্ট্রিক দ্বারা সরবরাহ করা হয়েছে। রোবোলেক্ট্রিক হল একটি লাইব্রেরি যা পরীক্ষার জন্য একটি সিমুলেটেড অ্যান্ড্রয়েড পরিবেশ তৈরি করে এবং এমুলেটর বুট করার বা ডিভাইসে চালানোর চেয়ে দ্রুত চলে। Roboelectric নির্ভরতা ছাড়া, আপনি এই ত্রুটি পাবেন:

@RunWith(AndroidJUnit4::class) কি করে?

একজন টেস্ট রানার একটি JUnit উপাদান যা পরীক্ষা চালায়। একটি পরীক্ষা রানার ছাড়া, আপনার পরীক্ষা চালানো হবে না. JUnit দ্বারা প্রদত্ত একটি ডিফল্ট পরীক্ষা রানার রয়েছে যা আপনি স্বয়ংক্রিয়ভাবে পাবেন। @RunWith সেই ডিফল্ট টেস্ট রানারকে অদলবদল করে।

AndroidJUnit4 টেস্ট রানার AndroidX টেস্টকে আপনার পরীক্ষাটি ভিন্নভাবে চালানোর অনুমতি দেয় যেগুলি যন্ত্রযুক্ত বা স্থানীয় পরীক্ষা কিনা তার উপর নির্ভর করে।

ধাপ 6. রোবোলেক্ট্রিক সতর্কতা ঠিক করুন

আপনি যখন কোডটি চালান, লক্ষ্য করুন যে Roboelectric ব্যবহার করা হয়েছে।

অ্যান্ড্রয়েডএক্স টেস্ট এবং অ্যান্ড্রয়েডজুনিট 4 টেস্ট রানারের কারণে, আপনি সরাসরি রোবোলেক্ট্রিক কোডের একটি লাইন না লিখে এটি করা হয়!

আপনি দুটি সতর্কতা লক্ষ্য করতে পারেন।

  • No such manifest file: ./AndroidManifest.xml
  • "WARN: Android SDK 29 requires Java 9..."

আপনি আপনার গ্রেডল ফাইল আপডেট করে এই No such manifest file: ./AndroidManifest.xml সতর্কতা।

  1. আপনার গ্রেডল ফাইলে নিম্নলিখিত লাইনটি যোগ করুন যাতে সঠিক অ্যান্ড্রয়েড ম্যানিফেস্ট ব্যবহার করা হয়। includeAndroidResources বিকল্পটি আপনাকে আপনার AndroidManifest ফাইল সহ আপনার ইউনিট পরীক্ষায় android সম্পদগুলি অ্যাক্সেস করতে দেয়।

app/build.gradle

    // Always show the result of every unit test when running via command line, even if it passes.
    testOptions.unitTests {
        includeAndroidResources = true

        // ... 
    }

সতর্কতা "WARN: Android SDK 29 requires Java 9..." আরও জটিল। Android Q-এ পরীক্ষা চালানোর জন্য Java 9 প্রয়োজন । জাভা 9 ব্যবহার করার জন্য Android স্টুডিও কনফিগার করার চেষ্টা করার পরিবর্তে, এই কোডল্যাবের জন্য, আপনার লক্ষ্য রাখুন এবং 28 এ SDK কম্পাইল করুন।

সংক্ষেপে:

  • বিশুদ্ধ ভিউ মডেল পরীক্ষাগুলি সাধারণত test উত্স সেটে যেতে পারে কারণ তাদের কোডের জন্য সাধারণত অ্যান্ড্রয়েডের প্রয়োজন হয় না।
  • অ্যাপ্লিকেশন এবং ক্রিয়াকলাপগুলির মতো উপাদানগুলির পরীক্ষামূলক সংস্করণ পেতে আপনি AndroidX পরীক্ষা লাইব্রেরি ব্যবহার করতে পারেন।
  • আপনার test উৎস সেটে সিমুলেটেড অ্যান্ড্রয়েড কোড চালানোর প্রয়োজন হলে, আপনি রোবোলেক্ট্রিক নির্ভরতা এবং @RunWith(AndroidJUnit4::class) টীকা যোগ করতে পারেন।

অভিনন্দন, আপনি একটি পরীক্ষা চালানোর জন্য AndroidX টেস্টিং লাইব্রেরি এবং Robolectric উভয়ই ব্যবহার করছেন৷ আপনার পরীক্ষা শেষ হয়নি (আপনি এখনও একটি দাবী বিবৃতি লেখেননি, এটি শুধু বলে // TODO test LiveData )। আপনি পরবর্তী LiveData দিয়ে দাবী বিবৃতি লিখতে শিখবেন।

এই টাস্কে, আপনি শিখবেন কিভাবে সঠিকভাবে LiveData মান জাহির করতে হয়।

এখানে আপনি addNewTask_setsNewTaskEvent ভিউ মডেল পরীক্ষা ছাড়াই ছেড়ে গেছেন।

TasksViewModelTest.kt

    @Test
    fun addNewTask_setsNewTaskEvent() {

        // Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

        // When adding a new task
        tasksViewModel.addNewTask()

        // Then the new task event is triggered
        // TODO test LiveData
    }
    

LiveData পরীক্ষা করার জন্য আপনাকে দুটি জিনিস করার পরামর্শ দেওয়া হচ্ছে:

  1. InstantTaskExecutorRule ব্যবহার করুন
  2. LiveData পর্যবেক্ষণ নিশ্চিত করুন

ধাপ 1. InstantTaskExecutorRule ব্যবহার করুন

InstantTaskExecutorRule হল একটি JUnit নিয়ম । আপনি যখন এটিকে @get:Rule টীকা দিয়ে ব্যবহার করেন, এটি InstantTaskExecutorRule ক্লাসে কিছু কোড পরীক্ষার আগে এবং পরে চালানোর কারণ হয় (সঠিক কোড দেখতে, আপনি ফাইলটি দেখতে কীবোর্ড শর্টকাট কমান্ড+বি ব্যবহার করতে পারেন)।

এই নিয়মটি একই থ্রেডে সমস্ত আর্কিটেকচার উপাদান-সম্পর্কিত ব্যাকগ্রাউন্ড কাজ চালায় যাতে পরীক্ষার ফলাফলগুলি সিঙ্ক্রোনাসভাবে এবং পুনরাবৃত্তিযোগ্য ক্রমে ঘটে। আপনি যখন পরীক্ষা লিখবেন যাতে লাইভডেটা পরীক্ষা করা অন্তর্ভুক্ত থাকে, এই নিয়মটি ব্যবহার করুন!

  1. আর্কিটেকচার কম্পোনেন্টস কোর টেস্টিং লাইব্রেরির জন্য গ্রেডেল নির্ভরতা যোগ করুন (যেটিতে এই নিয়ম রয়েছে)।

app/build.gradle

testImplementation "androidx.arch.core:core-testing:$archTestingVersion"
  1. TasksViewModelTest.kt খুলুন
  2. TasksViewModelTest ক্লাসের ভিতরে InstantTaskExecutorRule যোগ করুন।

TasksViewModelTest.kt

class TasksViewModelTest {
    @get:Rule
    var instantExecutorRule = InstantTaskExecutorRule()
    
    // Other code...
}

ধাপ 2. LiveDataTestUtil.kt ক্লাস যোগ করুন

আপনার পরবর্তী ধাপ হল আপনার পরীক্ষা করা LiveData পরিলক্ষিত হয়েছে তা নিশ্চিত করা।

আপনি যখন LiveData ব্যবহার করেন, তখন আপনার সাধারণত একটি কার্যকলাপ বা খণ্ড থাকে ( LifecycleOwner ) LiveData পর্যবেক্ষণ করেন।

viewModel.resultLiveData.observe(fragment, Observer {
    // Observer code here
})

এই পর্যবেক্ষণ গুরুত্বপূর্ণ. আপনার LiveData সক্রিয় পর্যবেক্ষক প্রয়োজন

  • যেকোনো onChanged ইভেন্ট ট্রিগার করুন।
  • যেকোনো রূপান্তর ট্রিগার করুন।

আপনার ভিউ মডেলের LiveData জন্য প্রত্যাশিত LiveData আচরণ পেতে, আপনাকে একজন LifecycleOwner সাথে LiveData পর্যবেক্ষণ করতে হবে।

এটি একটি সমস্যা তৈরি করে: আপনার TasksViewModel পরীক্ষায়, আপনার LiveData পর্যবেক্ষণ করার জন্য আপনার কাছে কোনো কার্যকলাপ বা খণ্ড নেই। এটির কাছাকাছি পেতে, আপনি observeForever পদ্ধতি ব্যবহার করতে পারেন, যা নিশ্চিত করে যে LifecycleOwner প্রয়োজন ছাড়াই LiveData ক্রমাগত পর্যবেক্ষণ করা হয়। আপনি যখন observeForever , তখন আপনাকে আপনার পর্যবেক্ষককে সরিয়ে ফেলার কথা মনে রাখতে হবে বা পর্যবেক্ষক ফাঁসের ঝুঁকি নিতে হবে।

এটি নীচের কোড মত কিছু দেখায়. এটি পরীক্ষা করুন:

@Test
fun addNewTask_setsNewTaskEvent() {

    // Given a fresh ViewModel
    val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())


    // Create observer - no need for it to do anything!
    val observer = Observer<Event<Unit>> {}
    try {

        // Observe the LiveData forever
        tasksViewModel.newTaskEvent.observeForever(observer)

        // When adding a new task
        tasksViewModel.addNewTask()

        // Then the new task event is triggered
        val value = tasksViewModel.newTaskEvent.value
        assertThat(value?.getContentIfNotHandled(), (not(nullValue())))

    } finally {
        // Whatever happens, don't forget to remove the observer!
        tasksViewModel.newTaskEvent.removeObserver(observer)
    }
}

এটি একটি পরীক্ষায় একটি একক LiveData পর্যবেক্ষণ করার জন্য অনেক বয়লারপ্লেট কোড! এই বয়লারপ্লেট থেকে মুক্তি পাওয়ার কয়েকটি উপায় রয়েছে। পর্যবেক্ষকদের যোগ করা সহজ করতে আপনি LiveDataTestUtil নামে একটি এক্সটেনশন ফাংশন তৈরি করতে যাচ্ছেন।

  1. আপনার test উত্স সেটে LiveDataTestUtil.kt নামে একটি নতুন Kotlin ফাইল তৈরি করুন৷


  1. নিচের কোডটি কপি করে পেস্ট করুন।

LiveDataTestUtil.kt

import androidx.annotation.VisibleForTesting
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException


@VisibleForTesting(otherwise = VisibleForTesting.NONE)
fun <T> LiveData<T>.getOrAwaitValue(
    time: Long = 2,
    timeUnit: TimeUnit = TimeUnit.SECONDS,
    afterObserve: () -> Unit = {}
): T {
    var data: T? = null
    val latch = CountDownLatch(1)
    val observer = object : Observer<T> {
        override fun onChanged(o: T?) {
            data = o
            latch.countDown()
            this@getOrAwaitValue.removeObserver(this)
        }
    }
    this.observeForever(observer)

    try {
        afterObserve.invoke()

        // Don't wait indefinitely if the LiveData is not set.
        if (!latch.await(time, timeUnit)) {
            throw TimeoutException("LiveData value was never set.")
        }

    } finally {
        this.removeObserver(observer)
    }

    @Suppress("UNCHECKED_CAST")
    return data as T
}

এটি একটি মোটামুটি জটিল পদ্ধতি। এটি getOrAwaitValue নামে একটি কোটলিন এক্সটেনশন ফাংশন তৈরি করে যা একজন পর্যবেক্ষককে যোগ করে, LiveData মান পায় এবং তারপর পর্যবেক্ষককে পরিষ্কার করে-মূলত উপরে দেখানো observeForever কোডের একটি সংক্ষিপ্ত, পুনরায় ব্যবহারযোগ্য সংস্করণ। এই ক্লাসের সম্পূর্ণ ব্যাখ্যার জন্য, এই ব্লগ পোস্টটি দেখুন।

ধাপ 3. দাবী লিখতে getOrAwaitValue ব্যবহার করুন

এই পদক্ষেপে, আপনি getOrAwaitValue পদ্ধতিটি ব্যবহার করেন এবং একটি দৃ statem ় বিবৃতি লিখুন যা newTaskEvent ট্রিগার করা হয়েছে তা যাচাই করে।

  1. getOrAwaitValue ব্যবহার করে newTaskEvent জন্য LiveData মান পান।
val value = tasksViewModel.newTaskEvent.getOrAwaitValue()
  1. দৃ sert ়ভাবে দাবি করুন যে মানটি বাতিল নয়।
assertThat(value.getContentIfNotHandled(), (not(nullValue())))

সম্পূর্ণ পরীক্ষাটি নীচের কোডের মতো দেখা উচিত।

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.example.android.architecture.blueprints.todoapp.getOrAwaitValue
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.not
import org.hamcrest.Matchers.nullValue
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class TasksViewModelTest {

    @get:Rule
    var instantExecutorRule = InstantTaskExecutorRule()


    @Test
    fun addNewTask_setsNewTaskEvent() {
        // Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

        // When adding a new task
        tasksViewModel.addNewTask()

        // Then the new task event is triggered
        val value = tasksViewModel.newTaskEvent.getOrAwaitValue()

        assertThat(value.getContentIfNotHandled(), not(nullValue()))


    }

}
  1. আপনার কোডটি চালান এবং পরীক্ষা পাস দেখুন!

এখন আপনি কীভাবে একটি পরীক্ষা লিখতে দেখেছেন, নিজে থেকে একটি লিখুন। এই পদক্ষেপে, আপনি যে দক্ষতাগুলি শিখেছেন তা ব্যবহার করে, অন্য TasksViewModel পরীক্ষা লেখার অনুশীলন করুন।

পদক্ষেপ 1। আপনার নিজের ভিউমোডেল পরীক্ষা লিখুন

আপনি setFilterAllTasks_tasksAddViewVisible() লিখবেন। এই পরীক্ষাটি পরীক্ষা করা উচিত যে আপনি যদি সমস্ত কাজগুলি দেখানোর জন্য আপনার ফিল্টার প্রকারটি সেট করেন তবে টাস্ক অ্যাড বোতামটি দৃশ্যমান।

  1. addNewTask_setsNewTaskEvent() ব্যবহার করে রেফারেন্সের জন্য, TasksViewModelTest একটি পরীক্ষা লিখুন setFilterAllTasks_tasksAddViewVisible() যা ALL_TASKS ফিল্টারিং মোড সেট করে এবং tasksAddViewVisible লাইভডাটা true বলে দাবি করে।


শুরু করতে নীচের কোডটি ব্যবহার করুন।

টাস্কভিউমোডেলস্টেস্ট

    @Test
    fun setFilterAllTasks_tasksAddViewVisible() {

        // Given a fresh ViewModel

        // When the filter type is ALL_TASKS

        // Then the "Add task" action is visible
        
    }

দ্রষ্টব্য:

  • সমস্ত কাজের জন্য TasksFilterType এনাম হ'ল ALL_TASKS.
  • কোনও কাজ যুক্ত করার জন্য বোতামটির দৃশ্যমানতা LiveData tasksAddViewVisible.
  1. আপনার পরীক্ষা চালান।

পদক্ষেপ 2। আপনার পরীক্ষার সমাধানের সাথে তুলনা করুন

নীচের সমাধানের সাথে আপনার সমাধানটি তুলনা করুন।

টাস্কভিউমোডেলস্টেস্ট

    @Test
    fun setFilterAllTasks_tasksAddViewVisible() {

        // Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

        // When the filter type is ALL_TASKS
        tasksViewModel.setFiltering(TasksFilterType.ALL_TASKS)

        // Then the "Add task" action is visible
        assertThat(tasksViewModel.tasksAddViewVisible.getOrAwaitValue(), `is`(true))
    }

আপনি নিম্নলিখিতগুলি করছেন কিনা তা পরীক্ষা করুন:

  • আপনি একই অ্যান্ড্রয়েডএক্স ApplicationProvider.getApplicationContext() বিবৃতি ব্যবহার করে আপনার tasksViewModel তৈরি করুন।
  • আপনি ALL_TASKS ফিল্টার টাইপ এনামে পাস করে setFiltering পদ্ধতিটি কল করুন।
  • আপনি পরীক্ষা করে দেখুন যে tasksAddViewVisible সত্য, getOrAwaitNextValue পদ্ধতি ব্যবহার করে।

পদক্ষেপ 3। একটি @এর আগে নিয়ম যুক্ত করুন

আপনার উভয় পরীক্ষার শুরুতে কীভাবে লক্ষ্য করুন, আপনি একটি TasksViewModel সংজ্ঞায়িত করেন।

টাস্কভিউমোডেলস্টেস্ট

        // Given a fresh ViewModel
        val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

আপনি যখন একাধিক পরীক্ষার জন্য পুনরাবৃত্তি সেটআপ কোডটি রেখেছেন, আপনি একটি সেটআপ পদ্ধতি তৈরি করতে এবং পুনরাবৃত্তি কোডটি অপসারণ করতে @ফোর আগে টীকাটি ব্যবহার করতে পারেন। যেহেতু এই সমস্ত পরীক্ষাগুলি TasksViewModel পরীক্ষা করতে চলেছে, এবং একটি ভিউ মডেল প্রয়োজন, তাই এই কোডটি @Before ব্লকে স্থানান্তরিত করুন।

  1. tasksViewModel| নামে পরিচিত একটি lateinit ইনস্ট্যান্স ভেরিয়েবল তৈরি করুন .
  2. setupViewModel নামে একটি পদ্ধতি তৈরি করুন।
  3. এটি @Before দিয়ে টীকা দিন।
  4. ভিউ মডেল ইনস্ট্যান্টেশন কোডটি setupViewModel সরান।

টাস্কভিউমোডেলস্টেস্ট

    // Subject under test
    private lateinit var tasksViewModel: TasksViewModel

    @Before
    fun setupViewModel() {
        tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
    }
  1. আপনার কোড চালান!

সতর্কতা

নিম্নলিখিতগুলি করবেন না , আরম্ভ করবেন না

tasksViewModel

এর সংজ্ঞা সহ:

val tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())

এটি সমস্ত পরীক্ষার জন্য একই উদাহরণ ব্যবহার করতে পারে। এটি আপনার এড়ানো উচিত কারণ প্রতিটি পরীক্ষার পরীক্ষার অধীনে বিষয়টির একটি নতুন উদাহরণ থাকা উচিত (এই ক্ষেত্রে ভিউমোডেল)।

TasksViewModelTest জন্য আপনার চূড়ান্ত কোডটি নীচের কোডের মতো দেখতে হবে।

টাস্কভিউমোডেলস্টেস্ট

@RunWith(AndroidJUnit4::class)
class TasksViewModelTest {

    // Subject under test
    private lateinit var tasksViewModel: TasksViewModel

    // Executes each task synchronously using Architecture Components.
    @get:Rule
    var instantExecutorRule = InstantTaskExecutorRule()

    @Before
    fun setupViewModel() {
        tasksViewModel = TasksViewModel(ApplicationProvider.getApplicationContext())
    }


    @Test
    fun addNewTask_setsNewTaskEvent() {

        // When adding a new task
        tasksViewModel.addNewTask()

        // Then the new task event is triggered
        val value = tasksViewModel.newTaskEvent.awaitNextValue()
        assertThat(
            value?.getContentIfNotHandled(), (not(nullValue()))
        )
    }

    @Test
    fun getTasksAddViewVisible() {

        // When the filter type is ALL_TASKS
        tasksViewModel.setFiltering(TasksFilterType.ALL_TASKS)

        // Then the "Add task" action is visible
        assertThat(tasksViewModel.tasksAddViewVisible.awaitNextValue(), `is`(true))
    }
    
}

আপনি শুরু করা কোড এবং চূড়ান্ত কোডের মধ্যে একটি পার্থক্য দেখতে এখানে ক্লিক করুন।

সমাপ্ত কোডেল্যাবের জন্য কোডটি ডাউনলোড করতে, আপনি নীচে গিট কমান্ডটি ব্যবহার করতে পারেন:

$ git clone https://github.com/googlecodelabs/android-testing.git
$ cd android-testing
$ git checkout end_codelab_1


বিকল্পভাবে আপনি জিপ ফাইল হিসাবে সংগ্রহস্থলটি ডাউনলোড করতে পারেন, এটি আনজিপ করতে পারেন এবং এটি অ্যান্ড্রয়েড স্টুডিওতে খুলতে পারেন।

জিপ ডাউনলোড করুন

এই কোডল্যাব আচ্ছাদিত:

উদাসীনতা কোর্স:

অ্যান্ড্রয়েড বিকাশকারী ডকুমেন্টেশন:

ভিডিও:

অন্যান্য:

এই কোর্সে অন্যান্য কোডল্যাবগুলির লিঙ্কগুলির জন্য, কোটলিন কোডল্যাবস ল্যান্ডিং পৃষ্ঠায় উন্নত অ্যান্ড্রয়েড দেখুন।