ऐप्लिकेशन को टारगेट करने का उदाहरण

इंस्ट्रुमेंटेशन परीक्षण की यह श्रेणी नियमित Android ऐप्लिकेशन को लक्षित करने वाली श्रेणियों से अलग नहीं है. ध्यान दें कि जिस टेस्ट ऐप्लिकेशन में इंस्ट्रूमेंटेशन शामिल है उस पर उसी सर्टिफ़िकेट से हस्ताक्षर करना ज़रूरी है जिस पर उस ऐप्लिकेशन पर हस्ताक्षर किया गया है जिसे टारगेट किया जा रहा है.

ध्यान दें कि इस गाइड में यह माना गया है कि आपको प्लैटफ़ॉर्म के सोर्स ट्री वर्कफ़्लो के बारे में पहले से कुछ जानकारी है. अगर ऐसा नहीं है, तो कृपया ज़रूरी शर्तें देखें. यहां दिए गए उदाहरण में, अपने टेस्ट ऐप्लिकेशन पैकेज पर सेट किए गए टारगेट पैकेज के साथ, नया इंस्ट्रूमेंटेशन टेस्ट लिखा जा रहा है. अगर आपको इस कॉन्सेप्ट के बारे में जानकारी नहीं है, तो कृपया प्लैटफ़ॉर्म टेस्टिंग के बारे में जानकारी पढ़ें.

इस गाइड में, सैंपल के तौर पर इस टेस्ट का इस्तेमाल किया गया है:

  • frameworks/base/packages/Shell/tests

हमारा सुझाव है कि आगे बढ़ने से पहले, कोड को ब्राउज़ करके उसका एक अनुमान लगा लें.

सोर्स की जगह तय करना

इंस्ट्रुमेंटेशन टेस्ट किसी ऐप्लिकेशन को टारगेट करेगा. इसलिए, टेस्ट सोर्स कोड को प्लैटफ़ॉर्म सोर्स ट्री में अपने कॉम्पोनेंट की सोर्स डायरेक्ट्री के रूट में, tests डायरेक्ट्री में रखने का तरीका है.

खुद को इंस्ट्रुमेंट करने वाले टेस्ट के लिए, एंड-टू-एंड उदाहरण में, सोर्स लोकेशन के बारे में ज़्यादा चर्चाएं देखें.

मेनिफ़ेस्ट फ़ाइल

किसी सामान्य ऐप्लिकेशन की तरह ही, हर इंस्ट्रूमेंटेशन टेस्ट मॉड्यूल के लिए एक मेनिफ़ेस्ट फ़ाइल की ज़रूरत होती है. अगर आपने फ़ाइल का नाम AndroidManifest.xml रखा है और उसे अपने टेस्ट टेंप्लेट के लिए Android.mk के बगल में दिया है, तो यह BUILD_PACKAGE कोर मेकफ़ाइल में अपने-आप शामिल हो जाएगी.

आगे बढ़ने से पहले, हमारा सुझाव है कि आप ऐप्लिकेशन मेनिफ़ेस्ट की खास जानकारी पढ़ें.

इस लेख में, मेनिफ़ेस्ट फ़ाइल के बुनियादी कॉम्पोनेंट और उनकी मुख्य सुविधाओं के बारे में बताया गया है.

सैंपल के तौर पर दिए गए gerrit बदलाव के लिए, मेनिफ़ेस्ट फ़ाइल का नया वर्शन यहां ऐक्सेस किया जा सकता है: https://android.googlesource.com/platform/frameworks/base/+/main/packages/Shell/tests/AndroidManifest.xml

सुविधा के लिए यहां एक स्नैपशॉट शामिल किया गया है:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.shell.tests">

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

        <activity
            android:name="com.android.shell.ActionSendMultipleConsumerActivity"
            android:label="ActionSendMultipleConsumer"
            android:theme="@android:style/Theme.NoDisplay"
            android:noHistory="true"
            android:excludeFromRecents="true">
            <intent-filter>
                <action android:name="android.intent.action.SEND_MULTIPLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="*/*" />
            </intent-filter>
        </activity>
    </application>

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
        android:targetPackage="com.android.shell"
        android:label="Tests for Shell" />

</manifest>

मेनिफ़ेस्ट फ़ाइल के बारे में कुछ खास बातें:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.shell.tests">

package एट्रिब्यूट, ऐप्लिकेशन पैकेज का नाम होता है: यह एक यूनीक आइडेंटिफ़ायर होता है. इसका इस्तेमाल, Android ऐप्लिकेशन फ़्रेमवर्क किसी ऐप्लिकेशन (या इस संदर्भ में: आपके टेस्ट ऐप्लिकेशन) की पहचान करने के लिए करता है. सिस्टम में मौजूद हर उपयोगकर्ता, उस पैकेज नाम से सिर्फ़ एक ऐप्लिकेशन इंस्टॉल कर सकता है.

यह टेस्ट ऐप्लिकेशन पैकेज है, जो टेस्ट किए जा रहे ऐप्लिकेशन पैकेज से अलग होता है. इसलिए, पैकेज के लिए कोई दूसरा नाम इस्तेमाल करना ज़रूरी है: एक सामान्य तरीका यह है कि पैकेज के नाम के बाद .test जोड़ें.

इसके अलावा, यह package एट्रिब्यूट, ComponentName#getPackageName() के रिटर्न जैसा ही होता है. साथ ही, यह वही एट्रिब्यूट होता है जिसका इस्तेमाल adb shell के ज़रिए अलग-अलग pm सब-कमांड के साथ इंटरैक्ट करने के लिए किया जाता है.

कृपया यह भी ध्यान दें कि आम तौर पर, पैकेज का नाम और Java पैकेज का नाम एक ही स्टाइल में होता है. हालांकि, दोनों में काफ़ी कम अंतर होता है. दूसरे शब्दों में, आपके ऐप्लिकेशन (या परीक्षण) पैकेज में किसी भी पैकेज नाम वाली क्लास शामिल हो सकती है, हालांकि दूसरी ओर, आप सरलता को चुन सकते हैं और अपने ऐप्लिकेशन में शीर्ष स्तर का Java पैकेज नाम रख सकते हैं या ऐप्लिकेशन पैकेज के नाम के समान परीक्षण कर सकते हैं.

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

यह सभी इंस्ट्रुमेंटेशन टेस्ट के लिए ज़रूरी है, क्योंकि मिलती-जुलती क्लास को एक अलग फ़्रेमवर्क जार लाइब्रेरी फ़ाइल में पैकेज किया जाता है. इसलिए, ऐप्लिकेशन फ़्रेमवर्क से टेस्ट पैकेज को शुरू करने पर, अतिरिक्त क्लासपाथ एंट्री की ज़रूरत होती है.

android:targetPackage="com.android.shell"

इससे, इंस्ट्रुमेंटेशन के टारगेट पैकेज को com.android.shell पर सेट किया जाता है. जब am instrument कमांड की मदद से इंस्ट्रुमेंटेशन को शुरू किया जाता है, तो फ़्रेमवर्क com.android.shell प्रोसेस को फिर से शुरू करता है. साथ ही, टेस्ट को लागू करने के लिए, प्रोसेस में इंस्ट्रुमेंटेशन कोड इंजेक्ट करता है. इसका मतलब यह भी है कि टेस्ट कोड के पास, जांचे जा रहे ऐप्लिकेशन में चल रहे सभी क्लास इंस्टेंस का ऐक्सेस होगा. साथ ही, टेस्ट के लिए उपलब्ध किए गए हुक के आधार पर, स्टेटस में बदलाव किया जा सकता है.

आसान कॉन्फ़िगरेशन फ़ाइल

हर नए टेस्ट मॉड्यूल में एक कॉन्फ़िगरेशन फ़ाइल होनी चाहिए, ताकि मॉड्यूल के मेटाडेटा, कंपाइल के समय की डिपेंडेंसी, और पैकेजिंग के निर्देशों के साथ बिल्ड सिस्टम को निर्देश दिया जा सके. ज़्यादातर मामलों में, सूंग पर आधारित ब्लूप्रिंट फ़ाइल का विकल्प ही काफ़ी होता है. ज़्यादा जानकारी के लिए, आसान टेस्ट कॉन्फ़िगरेशन देखें.

जटिल कॉन्फ़िगरेशन फ़ाइल

ज़्यादा मुश्किल टेस्ट के लिए, आपको Android के टेस्ट हार्नेस, Trade Federation के लिए टेस्ट कॉन्फ़िगरेशन फ़ाइल भी लिखनी होगी.

टेस्ट कॉन्फ़िगरेशन में, डिवाइस के सेटअप के खास विकल्प और टेस्ट क्लास की जानकारी देने के लिए डिफ़ॉल्ट आर्ग्युमेंट शामिल किए जा सकते हैं.

नमूना गेरिट बदलाव के लिए कॉन्फ़िगरेशन फ़ाइल के सबसे नए वर्शन को यहां ऐक्सेस किया जा सकता है: frameworks/base/packages/Shell/tests/AndroidTest.xml

आपकी सुविधा के लिए, यहां एक स्नैपशॉट दिया गया है:

<configuration description="Runs Tests for Shell.">
    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
        <option name="test-file-name" value="ShellTests.apk" />
    </target_preparer>

    <option name="test-suite-tag" value="apct" />
    <option name="test-tag" value="ShellTests" />
    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
        <option name="package" value="com.android.shell.tests" />
        <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="ShellTests.apk"/>
</target_preparer>

इससे ट्रेड फ़ेडरेशन को टारगेट डिवाइस पर ShellTests.apk इंस्टॉल करने का निर्देश मिलता है. इसके लिए, यह किसी खास टारगेट_तैयार करने वाले ऐप्लिकेशन का इस्तेमाल करता है. Trade Federation में डेवलपर के लिए कई टारगेट तैयार करने वाले टूल उपलब्ध हैं. इनका इस्तेमाल करके, यह पक्का किया जा सकता है कि जांच शुरू करने से पहले डिवाइस ठीक से सेट अप हो.

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

इससे, टेस्ट को चलाने के लिए इस्तेमाल की जाने वाली Trade Federation टेस्ट क्लास के बारे में पता चलता है. साथ ही, यह डिवाइस पर पैकेज में मौजूद पास और टेस्ट रनर फ़्रेमवर्क के बारे में भी बताता है. इस मामले में, यह JUnit है.

टेस्ट मॉड्यूल कॉन्फ़िगरेशन के बारे में ज़्यादा जानकारी पाने के लिए, यहां जाएं

JUnit4 की सुविधाएं

android-support-test लाइब्रेरी को टेस्ट रनर के तौर पर इस्तेमाल करने से, नई JUnit4 स्टाइल की टेस्ट क्लास को अपनाया जा सकता है. साथ ही, सैंपल gerrit बदलाव में इसकी सुविधाओं का कुछ बुनियादी इस्तेमाल शामिल है.

सैंपल के तौर पर दिए गए gerrit बदलाव का नया सोर्स कोड यहां ऐक्सेस किया जा सकता है: frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java

आम तौर पर, टेस्टिंग पैटर्न कॉम्पोनेंट टीमों के हिसाब से होते हैं. हालांकि, आम तौर पर इस्तेमाल किए जाने वाले कुछ काम के पैटर्न भी होते हैं.

@SmallTest
@RunWith(AndroidJUnit4.class)
public final class FeatureFactoryImplTest {

JUnit4 में एक अहम अंतर यह है कि अब टेस्ट को किसी सामान्य बेस टेस्ट क्लास से इनहेरिट करने की ज़रूरत नहीं है. इसके बजाय, टेस्ट को साधारण Java क्लास में लिखा जाता है और टेस्ट के कुछ सेटअप और सीमाओं को दिखाने के लिए एनोटेशन का इस्तेमाल किया जाता है. इस उदाहरण में, हम निर्देश दे रहे हैं कि इस क्लास को Android JUnit4 टेस्ट के तौर पर चलाया जाना चाहिए.

@SmallTest व्याख्या में पूरी टेस्ट क्लास के लिए एक टेस्ट साइज़ तय किया जाता है: इस टेस्ट क्लास में जोड़े गए सभी टेस्ट के तरीकों से, इस टेस्ट साइज़ एनोटेशन को इनहेरिट किया जाता है. प्री टेस्ट क्लास सेटअप, पोस्ट टेस्ट टियर डाउन, और पोस्ट टेस्ट क्लास को बंद करना: JUnit4 में setUp और tearDown तरीकों की तरह. Test एनोटेशन का इस्तेमाल, असल टेस्ट में एनोटेट करने के लिए किया जाता है.

    @Before
    public void setup() {
    ...
    @Test
    public void testGetProvider_shouldCacheProvider() {
    ...

@Before एनोटेशन का इस्तेमाल, JUnit4 के तरीकों पर किया जाता है, ताकि टेस्ट सेटअप करने से पहले की प्रोसेस पूरी की जा सके. इस उदाहरण में इसका इस्तेमाल नहीं किया गया है, लेकिन टेस्ट के बाद टियरडाउन के लिए @After भी है. इसी तरह, @BeforeClass और @AfterClass एनोटेशन का इस्तेमाल, JUnit4 के तरीकों पर किया जा सकता है. इससे, किसी टेस्ट क्लास में सभी टेस्ट को लागू करने से पहले सेटअप किया जा सकता है और बाद में उसे बंद किया जा सकता है. ध्यान दें कि क्लास-स्कोप सेटअप और टियरडाउन के तरीके स्टैटिक होने चाहिए.

जांच के तरीकों के लिए, JUnit के पुराने वर्शन के उलट, अब उन्हें test से शुरू करने की ज़रूरत नहीं है. इसके बजाय, हर तरीके को @Test के साथ एनोटेट किया जाना चाहिए. आम तौर पर, टेस्ट के तरीके सार्वजनिक होने चाहिए. साथ ही, इनमें कोई रिटर्न वैल्यू नहीं होनी चाहिए, कोई पैरामीटर नहीं होना चाहिए, और इनमें अपवाद भी हो सकते हैं.

        Context context = InstrumentationRegistry.getTargetContext();

JUnit4 टेस्ट के लिए, अब सामान्य बेस क्लास की ज़रूरत नहीं है. इसलिए, अब getContext() या getTargetContext() से बेस क्लास वाले तरीकों से Context इंस्टेंस पाना ज़रूरी नहीं है. इसके बजाय, नया टेस्ट रनर इन्हें InstrumentationRegistry से मैनेज करता है. इसके लिए, इंस्ट्रुमेंटेशन फ़्रेमवर्क की मदद से बनाया गया और पर्यावरण से जुड़ा सेटअप सेव किया जाता है. इस क्लास के ज़रिए, आपके पास इन्हें कॉल करने की भी सुविधा है:

  • getInstrumentation(): Instrumentation क्लास का इंस्टेंस
  • getArguments(): -e <key> <value> के ज़रिए am instrument को पास किए गए कमांड लाइन आर्ग्युमेंट

स्थानीय तौर पर बनाना और टेस्ट करना

इस्तेमाल के सबसे सामान्य उदाहरणों के लिए, Atest का इस्तेमाल करें.

ज़्यादा जटिल मामलों में, ज़्यादा कस्टमाइज़ेशन की ज़रूरत होती है. ऐसे मामलों में, इंस्ट्रूमेंटेशन के निर्देशों का पालन करें.