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

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

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

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

  • frameworks/base/packages/Shell/tests

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

تحديد الموقع الجغرافي المصدر

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

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

ملف البيان

وكما هو الحال مع التطبيقات العادية، يحتاج كل وحدة اختبار للأدوات إلى ملف بيان. إذا سمّيت الملف AndroidManifest.xml وقدّمته بجانب Android.mk لوحدة الاختبار، سيتم تضمينه تلقائيًا في ملف BUILD_PACKAGE الأساسي.

قبل المتابعة، ننصحك بشدة بالاطّلاع أولاً على نظرة عامة على بيان التطبيق.

تقدّم هذه الصفحة نظرة عامة على المكوّنات الأساسية لملف البيان ووظائفها.

يمكن الوصول إلى أحدث إصدار من ملف البيان الخاص بتغيير نموذج gerrit على الرابط: https://android.googlesource.com/platform/frameworks/base/+/android16-release/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.

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

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

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