مثال على استهداف تطبيق

لا تختلف هذه الفئة من اختبارات الأدوات كثيرًا عن تلك التي تستهدف تطبيقات Android العادية. تجدر الإشارة إلى أنّه يجب توقيع التطبيق التجريبي الذي يتضمّن أداة القياس بالشهادة نفسها المستخدَمة في التطبيق المستهدف.

يُرجى العِلم أنّ هذا الدليل يفترض أنّ لديك بعض المعرفة في سير عمل شجرة مصدر المنصة. إذا لم يكن الأمر كذلك، يُرجى الرجوع إلى المتطلبات. يتناول المثال الذي نتناوله هنا كتابة اختبار أداة قياس جديد مع ضبط الحزمة المستهدفة على حزمة تطبيق الاختبار الخاصة به. إذا لم تكن على دراية بالمفهوم، يُرجى الاطّلاع على مقدّمة عن اختبار المنصة.

يستخدم هذا الدليل الاختبار التالي ليكون بمثابة عيّنة:

  • frameworks/base/packages/Shell/tests

ننصحك بالتصفّح في الرمز أولاً للحصول على فكرة تقريبية قبل المتابعة.

تحديد موقع مصدر

بما أنّ اختبار أداة القياس سيستهدف تطبيقًا، فإنّ العرف هو وضع رمز المصدر للاختبار في دليل tests ضمن جذر دليل مصدر المكوّن في شجرة مصدر المنصة.

يمكنك الاطّلاع على مزيد من المناقشات حول الموقع الجغرافي للمصدر في المثال الشامل ل الاختبارات التي تستخدم أدوات القياس الذاتي.

ملف البيان

تمامًا مثل التطبيقات العادية، تحتاج كل وحدة اختبار للأدوات إلى ملف بيان. إذا سمّيت الملف باسم AndroidManifest.xml وقدّمته بجانب Android.mk لوحدة الاختبار tmodule، سيتم تضمينه تلقائيًا من خلال ملف الإنشاء الأساسي 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() ، وهي أيضًا السمة نفسها التي ستستخدمها للتفاعل مع مختلف pm الطلبات الفرعية من خلال adb shell.

يُرجى العلم أيضًا أنّه على الرغم من أنّ اسم الحزمة يكون عادةً بالأسلوب نفسه اسم حزمة Java، إلا أنّه لا يرتبط به كثيرًا. بعبارة أخرى، قد تحتوي حزمة تطبيقك (أو اختبارك) على فئات تتضمّن أي أسماء حِزم، ولكن من ناحية أخرى، يمكنك اختيار البساطة وجعل اسم حزمة Java من المستوى العلوي في تطبيقك أو اختبارك مطابقًا لاسم حزمة التطبيق.

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

هذا مطلوب لجميع اختبارات أداة Instrumentation لأنّ الفئات ذات الصلة يتم تجميعها في ملف مكتبة jar لإطار العمل المنفصل، وبالتالي تتطلّب إدخالات إضافية لمسار البحث عن الصفوف عند استدعاء حزمة الاختبار من خلال إطار عمل التطبيق.

android:targetPackage="com.android.shell"

يؤدي ذلك إلى ضبط الحزمة المستهدَفة لأدوات القياس على com.android.shell. عند استدعاء عملية القياس من خلال الأمر am instrument، يعيد إطار العمل تشغيل عملية com.android.shell ويُدخل رمز القياس في العملية لتشغيل الاختبار. ويعني ذلك أيضًا أنّ رمز الاختبار سيكون لديه إذن الوصول إلى جميع نُسخ الفئة التي تعمل في التطبيق الذي يخضع للاختبار، وقد يتمكن من التلاعب بالحالة استنادًا إلى نقاط الاختبار المعروضة.

ملف إعدادات بسيط

يجب أن تحتوي كل وحدة اختبار جديدة على ملفّ إعدادات لتوجيه نظام الإنشاء باستخدام البيانات الوصفية للوحدة والتبعيات في وقت الترجمة وتعليمات التعبئة. في معظم الحالات، يكون خيار ملف Blueprint المستنِد إلى Soong مناسبًا. راجِع إعداد الاختبار البسيط لمعرفة التفاصيل.

ملف إعدادات معقّد

بالنسبة إلى الاختبارات الأكثر تعقيدًا، عليك أيضًا كتابة ملف إعدادات اختبار لنظام اختبار Android، وهو Trade Federation.

يمكن أن تحدِّد إعدادات الاختبار خيارات إعداد الجهاز الخاصة وargv التلقائية لتوفير فئة الاختبار.

يمكن الوصول إلى أحدث إصدار من ملف الإعدادات لنموذج التغيير في Gerrit على الرابط: 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>

يطلب هذا من Trade Federation تثبيت ShellTests.apk على الجهاز المستهدَف باستخدام target_preparer محدّد. هناك العديد من أدوات إعداد الأجهزة المستهدفة التي تتوفّر للمطوّرين في 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 كمشغِّل اختبارات إمكانية استخدام klassen اختبار جديدة بأسلوب 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 حجم اختبار لفئة الاختبار بأكملها: ترث كل setUp طرق الاختبار المُضافة إلى فئة الاختبار هذه التعليق التوضيحي لحجم الاختبار. إعداد فئة الاختبار قبل الاختبار وإزالتها بعد الاختبار وإزالتها بعد الاختبار: تشبه setUp وtearDown في JUnit4. يُستخدَم التعليق التوضيحي Test لإضافة تعليقات توضيحية إلى الاختبار الفعلي.

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

يتم استخدام التعليق التوضيحي @Before على الطرق من خلال JUnit4 لإجراء عملية الإعداد قبل الاختبار. على الرغم من عدم استخدام @After في هذا المثال، إلا أنّه يمكن استخدامه أيضًا لإزالة الاختبار بعد الانتهاء منه. وبالمثل، يمكن استخدام التعليقَين التوضيحيَين @BeforeClass و@AfterClass في الطرق من خلال JUnit4 لتنفيذ الإعداد قبل تنفيذ جميع الاختبارات في فئة اختبار، وعمليات الإزالة بعد ذلك. يُرجى العلم أنّه يجب أن تكون وظيفتا الإعداد والإزالة على مستوى الفئة ثابتتَين.

بالنسبة إلى طرق الاختبار، على عكس الإصدارات السابقة من JUnit، لم تعُد هناك حاجة لبدء اسم الطريقة بالرمز test، وبدلاً من ذلك، يجب وضع تعليق توضيحي باستخدام الرمز @Test على كل منها. وكما هو معتاد، يجب أن تكون طرق الاختبار علنية، وألا تحدّد أي قيمة معروضة، وألا تأخذ أيّ معلَمات، وقد تُعرِض استثناءات.

        Context context = InstrumentationRegistry.getTargetContext();

بما أنّ اختبارات JUnit4 لم تعُد تتطلّب فئة أساسية مشتركة، لم يعُد ضروريًا الحصول على نُسخ من Context من خلال getContext() أو getTargetContext() من خلال طرق الفئة الأساسية. بدلاً من ذلك، يُدير أداة تنفيذ الاختبار الجديدة هذه النُسخ من خلال InstrumentationRegistry حيث يتم تخزين الإعدادات السياقية والبيئية التي أنشأها إطار عمل الأدوات. من خلال هذه الفئة، يمكنك أيضًا استدعاء ما يلي:

  • getInstrumentation(): مثيل فئة Instrumentation
  • getArguments(): وسيطات سطر الأوامر التي تم تمريرها إلى am instrument من خلال -e <key> <value>

الإنشاء والاختبار على الجهاز

بالنسبة إلى حالات الاستخدام الأكثر شيوعًا، استخدِم Atest.

بالنسبة إلى الحالات الأكثر تعقيدًا التي تتطلّب تخصيصًا أكبر، اتّبِع تعليمات إعداد الأدوات.