مثال على اختبارات الأجهزة الذاتية

عند بدء اختبار أداة قياس الأداء، تتم إعادة تشغيل الحزمة المستهدفة مع إدخال رمز أداة قياس الأداء وبدء تنفيذه. وثمة استثناء، هو أنّ الحزمة المستهدفة هنا لا يمكن أن تكون إطار عمل تطبيق Android نفسه، مثل الحزمة android، لأنّ ذلك يؤدي إلى موقف متناقض يتطلّب إعادة تشغيل إطار عمل Android، وهو ما يدعم وظائف النظام، بما في ذلك الأداة نفسها.

وهذا يعني أنّه لا يمكن لاختبار أداة القياس إدخال نفسه في إطار عمل Android ، المعروف أيضًا باسم خادم النظام، لتنفيذه. لاختبار إطار عمل Android ، لا يمكن لرمز الاختبار استدعاء سوى مساحات عرض واجهات برمجة التطبيقات المتاحة للجميع، أو تلك التي تم الكشف عنها باستخدام لغة تعريف واجهة Android AIDL المتوفّرة في شجرة مصدر النظام الأساسي. بالنسبة إلى هذه الفئة من الاختبارات، ليس من المفيد استهداف أي حزمة معيّنة. لذلك، من المعتاد أن يتمّ تحديد هذه الأدوات لاستهداف حزمة تطبيق الاختبار الخاصة بها، كما هو محدّد في علامة <manifest> الخاصة بها من AndroidManifest.xml.

استنادًا إلى المتطلبات، قد تؤدي حِزم تطبيقات الاختبار في هذه الفئة أيضًا إلى:

  • يجب تجميع الأنشطة لإجراء الاختبار.
  • شارِك رقم تعريف المستخدم مع النظام.
  • أن تكون موقَّعة باستخدام مفتاح المنصة
  • أن يتم تجميعها باستخدام مصدر إطار العمل بدلاً من حزمة SDK العامة

يُشار أحيانًا إلى فئة اختبارات الأدوات باسم الأدوات الذاتية. في ما يلي بعض الأمثلة على اختبارات الأدوات الذاتية في مصدر المنصة:

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

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

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

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

بافتراض أنّ الموقع الجذر لمصدر المكوّن هو <component source root>، تتضمّن معظم المكوّنات مجلدات src وtests ضمنه، وبعض الملفات الإضافية مثل Android.mk (أو مقسّمة إلى ملفات .mk إضافية) وملف البيان AndroidManifest.xml وملف الإعداد التجريبي AndroidTest.xml.

بما أنّك تضيف اختبارًا جديدًا تمامًا، قد تحتاج على الأرجح إلى إنشاء الدليل tests بجانب المكوّن src، وملؤه بالمحتوى.

في بعض الحالات، قد يمتلك فريقك هياكل أدلة أخرى ضمن tests بسبب الحاجة إلى تجميع مجموعات مختلفة من الاختبارات في حزم APK فردية. وفي هذه الحالة، ستحتاج إلى إنشاء دليل فرعي جديد ضمن tests.

بغض النظر عن البنية، سينتهي بك الأمر بملء الدليل tests أو الدليل الفرعي الذي تم إنشاؤه حديثًا بملفات مشابهة لما هو في الدليل instrumentation في نموذج تغيير gerrit. يتم شرح تفاصيل كل ملف لاحقًا في هذا المستند.

ملف البيان

كما هو الحال مع مشروع التطبيق، تتطلب كل وحدة اختبار أدوات ملف بيان يُسمى 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، ولكنّه لا يرتبط به كثيرًا. بعبارةٍ أخرى، قد تحتوي حزمة تطبيقك (أو اختبارك) على فئات تتضمّن أي أسماء حِزم، ولكن يمكنك من ناحية أخرى اختيار البساطة وجعل اسم حزمة Java من المستوى العلوي في تطبيقك أو اختبارك مطابقًا لاسم حزمة التطبيق.

android:sharedUserId="android.uid.system"

يشير ذلك إلى أنّه في وقت التثبيت، يجب منح ملف APK هذا رقم تعريف المستخدم نفسه، أي هوية وقت التشغيل، مثل المنصة الأساسية. يُرجى العلم أنّ ذلك يعتمد على توقيع حزمة APK باستخدام الشهادة نفسها المستخدَمة في النظام الأساسي الأساسي (راجِع LOCAL_CERTIFICATE في قسم سابق)، إلا أنّهما مفهومان مختلفان:

  • بعض الأذونات أو واجهات برمجة التطبيقات محمية بالتوقيع، مما يتطلب شهادة التوقيع نفسها
  • تتطلّب بعض الأذونات أو واجهات برمجة التطبيقات هوية system للمتصل، ما يتطلّب من حزمة المتصل مشاركة معرّف المستخدم مع system، إذا كانت حزمة منفصلة عن النظام الأساسي نفسه.
<uses-library android:name="android.test.runner" />

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

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

ربما لاحظت أنّه تمّ تحديد سمة targetPackage هنا على أنّها سمة package نفسها المحدّدة في علامة manifest لهذا الملف. كما هو موضّح في أساسيات الاختبار، فإنّ فئة اختبارات الأدوات هذه مخصّصة عادةً لاختبار واجهات برمجة التطبيقات الخاصة بالإطارات، لذا ليس من المفيد كثيرًا أن تحتوي على حِزمة تطبيق مستهدفة محدّدة غير نفسها.

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

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

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

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

يمكن أن تحدِّد إعدادات الاختبار خيارات إعداد جهاز خاصة ودلايلات default لتوفير فئة الاختبار. يمكنك الاطّلاع على المثال على الرابط /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 تثبيت HelloWorldTests.apk على الجهاز المستهدَف باستخدام target_preparer محدّد. هناك العديد من تجهيزات الاستهداف المتاحة لمطوّري البرامج في Trade Federation ويمكن استخدامها لضمان إعداد الجهاز بشكلٍ صحيح قبل تنفيذ الاختبار.

<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>

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

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

الوصول إلى فئة الأدوات

على الرغم من أنّه لم يتم تناول هذا الموضوع في مثال "مرحبًا" الأساسي، من الشائع أن يتطلّب اختبار Android الوصول إلى مثيل Instrumentation: هذه هي واجهة برمجة التطبيقات الأساسية التي توفّر إمكانية الوصول إلى سياقات التطبيقات وواجهات برمجة التطبيقات ذات الصلة بالنشاط وأكثر.

بما أنّ اختبارات JUnit4 لم تعُد تتطلّب فئة أساسية مشتركة، لم يعد ضروريًا الحصول على مثيل Instrumentation من خلال InstrumentationTestCase#getInstrumentation()، وبدلاً من ذلك، يدير أداة تنفيذ الاختبار الجديدة الإعداد السياقي والبيئي الذي أنشأه إطار عمل الأدوات .InstrumentationRegistry

للوصول إلى مثيل فئة Instrumentation، ما عليك سوى استدعاء الطريقة الثابتة getInstrumentation() في فئة InstrumentationRegistry:

Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation()

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

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

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