সেল্ফ-ইনস্ট্রুমেন্টিং টেস্টের উদাহরণ

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

এর অর্থ হল, কোনও ইনস্ট্রুমেন্টেশন টেস্ট, এক্সিকিউশনের জন্য Android ফ্রেমওয়ার্ক, অর্থাৎ সিস্টেম সার্ভারে নিজেকে ইনজেক্ট করতে পারে না। Android ফ্রেমওয়ার্ক পরীক্ষা করার জন্য, টেস্ট কোড শুধুমাত্র পাবলিক API সারফেস বা Android ইন্টারফেস ডেফিনিশন ল্যাঙ্গুয়েজ AIDL ব্যবহার করে এক্সপোজ করা সারফেসকে ইনভোক করতে পারে যা প্ল্যাটফর্ম সোর্স ট্রি-তে উপলভ্য। এই ধরনের পরীক্ষার ক্ষেত্রে, কোনও নির্দিষ্ট প্যাকেজকে টার্গেট করা অর্থপূর্ণ নয়। তাই, এই ধরনের ইনস্ট্রুমেন্টেশনকে তার নিজস্ব টেস্ট অ্যাপ্লিকেশন প্যাকেজ টার্গেট করার জন্য ঘোষণা করা প্রথাগত, যেমন এর নিজস্ব <manifest> ট্যাগে AndroidManifest.xml সংজ্ঞায়িত করা হয়েছে।

প্রয়োজনীয়তার উপর নির্ভর করে, এই বিভাগের টেস্ট অ্যাপ্লিকেশন প্যাকেজগুলিও এগুলি করতে পারে:

  • পরীক্ষা করার জন্য বান্ডেল অ্যাক্টিভিটি প্রয়োজন।
  • সিস্টেমের সাথে ব্যবহারকারীর আইডি শেয়ার করুন।
  • প্ল্যাটফর্ম 'কী' দিয়ে সাইন করা থাকতে হবে।
  • পাবলিক SDK-এর পরিবর্তে ফ্রেমওয়ার্ক সোর্সের সাথে কম্পাইল করা হতে হবে।

ইন্সট্রুমেন্টেশন টেস্টের এই বিভাগকে কখনও কখনও সেল্ফ-ইন্সট্রুমেন্টেশন বলা হয়। প্ল্যাটফর্ম সোর্সে সেল্ফ-ইনস্ট্রুমেন্টেশন টেস্টের কিছু উদাহরণ এখানে দেওয়া হল:

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

এগিয়ে যাওয়ার আগে কোডটি একবার ব্রাউজ করে নিলে ভালো হয়, তাহলে একটি প্রাথমিক ধারণা পাওয়া যায়।

সোর্স লোকেশন ঠিক করা

সাধারণত, আপনার টিমের কাছে কোড চেক-ইন করার জায়গা এবং টেস্ট যোগ করার জায়গা সংক্রান্ত একটি প্রতিষ্ঠিত প্যাটার্ন আগে থেকেই থাকবে। বেশিরভাগ টিমের একটি করে Git রিপোজিটরি থাকে অথবা অন্য টিমের সাথে একটি রিপোজিটরি শেয়ার করে, তবে কম্পোনেন্ট সোর্স কোড থাকার জন্য একটি আলাদা সাব-ডিরেক্টরি থাকে।

আপনার কম্পোনেন্ট সোর্সের রুট লোকেশন <component source root>-এ আছে বলে ধরে নিলে, বেশিরভাগ কম্পোনেন্টের এর অধীনে src এবং tests ফোল্ডার থাকে এবং কিছু অতিরিক্ত ফাইল যেমন Android.mk (বা অতিরিক্ত .mk ফাইলে বিভক্ত), ম্যানিফেস্ট ফাইল AndroidManifest.xml এবং টেস্ট কনফিগারেশন ফাইল 'AndroidTest.xml' থাকে।

আপনি যেহেতু একদম নতুন টেস্ট যোগ করছেন, তাই আপনাকে সম্ভবত tests আপনার কম্পোনেন্টের পাশে ডিরেক্টরি src তৈরি করতে হবে এবং কন্টেন্ট দিয়ে এটি পূরণ করতে হবে।

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

গঠন যাই হোক না কেন, আপনি tests ডিরেক্টরি বা নতুন তৈরি সাব-ডিরেক্টরিকে স্যাম্পেল গেরিট পরিবর্তনে instrumentation ডিরেক্টরির মতো ফাইল দিয়ে পূরণ করবেন। প্রতিটি ফাইলের বিবরণ এই ডকুমেন্টে পরে ব্যাখ্যা করা হয়েছে।

ম্যানিফেস্ট ফাইল

অ্যাপ প্রোজেক্টের মতো, প্রতিটি ইন্সট্রুমেন্টেশন টেস্ট মডিউলের জন্য AndroidManifest.xml নামের একটি ম্যানিফেস্ট ফাইল প্রয়োজন। BUILD_PACKAGEকোর মেকফাইল ব্যবহার করে এই ফাইলটি অটোমেটিক অন্তর্ভুক্ত করতে, আপনার টেস্ট মডিউলের ফাইলের পাশে এই ফাইলটি দিন। Android.mk

আপনি AndroidManifest.xml ফাইল সম্পর্কে পরিচিত না হলে, অ্যাপ ম্যানিফেস্ট ওভারভিউ দেখুন

নিচে একটি স্যাম্পেল AndroidManifest.xml ফাইল দেওয়া হল:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  android:sharedUserId="android.uid.system"
  package="android.test.example.helloworld" >

    <application>
       <uses-library android:name="android.test.runner"/>
    </application>

    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                     android:targetPackage="android.test.example.helloworld"
                     android:label="Hello World Test"/>

</manifest>

ম্যানিফেস্ট ফাইলে কিছু বেছে নেওয়া মন্তব্য:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

package অ্যাট্রিবিউট হল অ্যাপ্লিকেশন প্যাকেজের নাম: এটি হল অনন্য শনাক্তকারী যা Android অ্যাপ্লিকেশন ফ্রেমওয়ার্ক কোনও অ্যাপ্লিকেশন (বা এই প্রসঙ্গে: আপনার টেস্ট অ্যাপ্লিকেশন) শনাক্ত করতে ব্যবহার করে। সিস্টেমের প্রত্যেক ব্যবহারকারী সেই প্যাকেজের নাম দিয়ে শুধুমাত্র একটি অ্যাপ্লিকেশন ইনস্টল করতে পারবেন।

এছাড়াও, এই package অ্যাট্রিবিউটটি ComponentName#getPackageName() যা রিটার্ন করে তার মতোই এবং বিভিন্ন pm সাব কমান্ডের সাথে ইন্টার‍্যাক্ট করার জন্য আপনি যা ব্যবহার করেন তার মতোই adb shell ব্যবহার করে।

মনে রাখবেন, প্যাকেজের নাম সাধারণত Java প্যাকেজের নামের মতো একই স্টাইলে হলেও, আসলে এর সাথে খুব কম জিনিসই করতে হয়। অন্য কথায়, আপনার অ্যাপ্লিকেশন (বা টেস্ট) প্যাকেজে যেকোনও প্যাকেজের নাম সহ ক্লাস থাকতে পারে, যদিও অন্যদিকে, আপনি সরলতার জন্য বেছে নিতে পারেন এবং আপনার অ্যাপ্লিকেশনে আপনার টপ লেভেল জাভা প্যাকেজের নাম বা অ্যাপ্লিকেশন প্যাকেজের নামের মতো টেস্ট করতে পারেন।

android:sharedUserId="android.uid.system"

এটি ঘোষণা করে যে ইনস্টলেশনের সময়, এই APK ফাইলটিকে কোর প্ল্যাটফর্মের মতো একই ব্যবহারকারী আইডি, অর্থাৎ রানটাইম পরিচয় প্রদান করতে হবে। মনে রাখবেন, এটি কোর প্ল্যাটফর্মের মতো একই সার্টিফিকেট দিয়ে সাইন করা apk-এর উপর নির্ভরশীল (আগের বিভাগে LOCAL_CERTIFICATE দেখুন), তবে এগুলি আলাদা ধারণা:

  • কিছু অনুমতি বা API স্বাক্ষর সুরক্ষিত, যার জন্য একই স্বাক্ষর সার্টিফিকেট প্রয়োজন
  • কিছু অনুমতি বা API-এর জন্য system কলারের ব্যবহারকারীর পরিচয় প্রয়োজন হয়, যার জন্য কলিং প্যাকেজকে system-এর সাথে ব্যবহারকারীর আইডি শেয়ার করতে হয়, যদি এটি কোর প্ল্যাটফর্ম থেকে আলাদা প্যাকেজ হয়
<uses-library android:name="android.test.runner" />

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

android:targetPackage="android.test.example.helloworld"

আপনি হয়ত লক্ষ্য করেছেন যে targetPackage এখানে এই ফাইলের manifest ট্যাগে ঘোষিত অ্যাট্রিবিউটের package মতোই ঘোষণা করা হয়েছে। টেস্টিংয়ের প্রাথমিক তথ্যতে যেমন উল্লেখ করা হয়েছে, এই ধরনের ইন্সট্রুমেন্টেশন টেস্ট সাধারণত ফ্রেমওয়ার্ক API টেস্ট করার জন্য ব্যবহার করা হয়, তাই এটির জন্য নির্দিষ্ট টার্গেট করা অ্যাপ্লিকেশন প্যাকেজ থাকা খুব একটা অর্থপূর্ণ নয়।

সহজ কনফিগারেশন ফাইল

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

জটিল কনফিগারেশন ফাইল

এইসব আরও জটিল ঘটনার ক্ষেত্রে, আপনাকে Android-এর টেস্ট হার্নেস, ট্রেড ফেডারেশন-এর জন্য একটি টেস্ট কনফিগারেশন ফাইলও লিখতে হবে।

টেস্ট কনফিগারেশন, টেস্ট ক্লাসকে সাপ্লাই করার জন্য বিশেষ ডিভাইস সেট-আপ বিকল্প ও ডিফল্ট আর্গুমেন্ট নির্দিষ্ট করতে পারে। /platform_testing/tests/example/instrumentation/AndroidTest.xml-এ উদাহরণ দেখুন।

সুবিধার জন্য এখানে একটি স্ন্যাপশট অন্তর্ভুক্ত করা হয়েছে:

<configuration description="Runs sample instrumentation test.">
  <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
  <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
    <option name="test-file-name" value="HelloWorldTests.apk"/>
  </target_preparer>
  <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
  <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
  <option name="test-suite-tag" value="apct"/>
  <option name="test-tag" value="SampleInstrumentationTest"/>

  <test class="com.android.tradefed.testtype.AndroidJUnitTest">
    <option name="package" value="android.test.example.helloworld"/>
    <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
  </test>
</configuration>

টেস্ট কনফিগারেশন ফাইল সম্পর্কে কিছু বাছাই করা মন্তব্য:

<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
  <option name="test-file-name" value="HelloWorldTests.apk"/>
</target_preparer>

এটি Trade Federation-কে নির্দিষ্ট target_preparer ব্যবহার করে টার্গেট ডিভাইসে HelloWorldTests.apk ইনস্টল করতে বলে। ট্রেড ফেডারেশনে ডেভেলপারদের জন্য অনেক টার্গেট প্রিপেয়ারার উপলভ্য আছে এবং টেস্ট এক্সিকিউশনের আগে ডিভাইস সঠিকভাবে সেট-আপ করা হয়েছে কিনা তা নিশ্চিত করতে এগুলি ব্যবহার করা যেতে পারে।

<test class="com.android.tradefed.testtype.AndroidJUnitTest">
  <option name="package" value="android.test.example.helloworld"/>
  <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>

এটি টেস্ট চালানোর জন্য ব্যবহার করা Trade Federation টেস্ট ক্লাস এবং ডিভাইসে চালানোর জন্য প্যাকেজে পাস করা এবং টেস্ট রানার ফ্রেমওয়ার্ক নির্দিষ্ট করে, এই ক্ষেত্রে JUnit।

আরও তথ্যের জন্য, টেস্ট মডিউল কনফিগারেশন দেখুন।

JUnit4 ফিচার

android-support-test লাইব্রেরিকে টেস্ট রানার হিসেবে ব্যবহার করলে নতুন JUnit4 স্টাইলের টেস্ট ক্লাস গ্রহণ করা যায় এবং স্যাম্পেল Gerrit পরিবর্তনটিতে এর ফিচারের কিছু খুব প্রাথমিক ব্যবহার রয়েছে। /platform_testing/tests/example/instrumentation/src/android/test/example/helloworld/HelloWorldTest.java-এ উদাহরণ দেখুন।

যদিও টেস্টিং প্যাটার্ন সাধারণত কম্পোনেন্ট টিমের জন্য নির্দিষ্ট হয়, তবে কিছু সাধারণত উপযোগী ব্যবহারের প্যাটার্নও থাকে।

@RunWith(JUnit4.class)
public class HelloWorldTest {

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

    @BeforeClass
    public static void beforeClass() {
    ...
    @AfterClass
    public static void afterClass() {
    ...
    @Before
    public void before() {
    ...
    @After
    public void after() {
    ...
    @Test
    @SmallTest
    public void testHelloWorld() {
    ...

JUnit4-এর মাধ্যমে প্রি-টেস্ট সেট-আপ ও পোস্ট-টেস্ট টিয়ারডাউন পারফর্ম করার জন্য @Before ও @After অ্যানোটেশন ব্যবহার করা হয়। একইভাবে, JUnit4-এর মাধ্যমে @BeforeClass এবং @AfterClass অ্যানোটেশন মেথডে ব্যবহার করা হয় যাতে টেস্ট ক্লাসে সব টেস্ট এক্সিকিউট করার আগে সেট-আপ এবং পরে টিয়ারডাউন করা যায়। মনে রাখবেন যে ক্লাস-স্কোপ সেট-আপ ও টিয়ারডাউন পদ্ধতি অবশ্যই স্ট্যাটিক হতে হবে। পরীক্ষা পদ্ধতির ক্ষেত্রে, JUnit-এর আগের ভার্সনের মতো, সেগুলির আর পদ্ধতির নাম test দিয়ে শুরু করতে হবে না, পরিবর্তে, প্রত্যেকটিকে @Test দিয়ে অ্যানোটেট করতে হবে। যথারীতি, পরীক্ষা পদ্ধতি অবশ্যই সর্বজনীন হতে হবে, কোনও রিটার্ন ভ্যালু ঘোষণা করা যাবে না, কোনও প্যারামিটার নেওয়া যাবে না এবং ব্যতিক্রম দেখাতে পারে।

ইনস্ট্রুমেন্টেশন ক্লাস অ্যাক্সেস

যদিও 'হ্যালো ওয়ার্ল্ড' কোডের প্রাথমিক উদাহরণে এটি কভার করা হয়নি, তবে কোনও Android টেস্টের জন্য Instrumentation ইনস্ট্যান্স অ্যাক্সেস করার প্রয়োজন হওয়া খুবই সাধারণ ব্যাপার: এটি হল মূল API ইন্টারফেস যা অ্যাপ্লিকেশন কনটেক্সট, অ্যাক্টিভিটি লাইফসাইকেল সম্পর্কিত টেস্ট API এবং আরও অনেক কিছুতে অ্যাক্সেস প্রদান করে।

যেহেতু JUnit4 টেস্টের জন্য আর কোনও সাধারণ বেস ক্লাস প্রয়োজন হয় না, তাই Instrumentation ইনস্ট্যান্স InstrumentationTestCase#getInstrumentation()-এর মাধ্যমে পাওয়ার আর প্রয়োজন নেই, পরিবর্তে, নতুন টেস্ট রানার InstrumentationRegistry-এর মাধ্যমে এটি ম্যানেজ করে যেখানে ইন্সট্রুমেন্টেশন ফ্রেমওয়ার্কের তৈরি করা প্রাসঙ্গিক ও এনভায়রনমেন্টাল সেট-আপ স্টোর করা হয়।

Instrumentation class-এর ইনস্ট্যান্স অ্যাক্সেস করতে, InstrumentationRegistry class-এ শুধু স্ট্যাটিক মেথড getInstrumentation() কল করুন:

Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation()

লোকাল ডিভাইসে বিল্ড ও টেস্ট করা

সবচেয়ে সাধারণ ব্যবহারের ক্ষেত্রে, Atest ব্যবহার করুন।

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