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

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

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

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

  • أُطر العمل/base/الحزم/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() ، وهي أيضًا السمة نفسها التي ستستخدمها للتفاعل مع مختلف 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>

يحدد هذا الخيار فئة اختبار اتحاد التجارة المراد استخدامها لتنفيذ الاختبار واجتيازات الحزمة على الجهاز المراد تنفيذها وإطار عمل عدّاء الاختبار وهو 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 و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.

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