موارد تخزين إسبريسو

يمثل مورد الخمول عملية غير متزامنة تؤثر نتائجها في العمليات اللاحقة في اختبار واجهة المستخدم. من خلال تسجيل موارد عدم النشاط باستخدام Espresso، يمكنك التحقق من صحة هذه العمليات غير المتزامنة بشكل أكثر موثوقية عند اختبار تطبيقك.

تحديد الحالات التي تكون هناك حاجة فيها إلى عدم النشاط

يوفر Espresso مجموعة متطورة من إمكانات المزامنة. مع ذلك، تنطبق خاصية إطار العمل هذه فقط على العمليات التي تنشر الرسائل على MessageQueue، مثل الفئة الفرعية من View التي ترسم محتواها على الشاشة.

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

إذا كنت لا تستخدم موارد عدم النشاط عند اختبار نتائج العمل غير المتزامن لتطبيقك، فقد تجد نفسك مضطرًا لاستخدام أحد الحلول السيئة التالية لتحسين موثوقية اختباراتك:

  • جارٍ إضافة مكالمات إلى Thread.sleep(). عند إضافة مهلات اصطناعية إلى اختباراتك، يستغرق الأمر وقتًا أطول حتى تنتهي مجموعة الاختبار من التنفيذ، وقد تفشل اختباراتك في بعض الأحيان عند تنفيذها على أجهزة أبطأ. بالإضافة إلى ذلك، لا تتسع حالات التأخير هذه بشكل جيد، حيث قد يحتاج تطبيقك إلى أداء عمل غير متزامن يستغرق وقتًا أطول في إصدار مستقبلي.
  • تنفيذ برامج تضمين إعادة المحاولة، التي تستخدم حلقة التكرار للتحقق بشكل متكرر مما إذا كان تطبيقك لا يزال يؤدي عملاً غير متزامن حتى انتهاء المهلة. حتى إذا حددت الحد الأقصى لعدد المحاولات في الاختبارات، تستهلك كل عملية إعادة تنفيذ موارد النظام، وخاصةً وحدة المعالجة المركزية (CPU).
  • استخدام مثيلات CountDownLatch التي تسمح لسلسلة محادثات واحدة أو أكثر بالانتظار حتى يكتمل تنفيذ عدد معيّن من العمليات في سلسلة محادثات أخرى تتطلب منك هذه الكائنات تحديد طول المهلة الزمنية؛ وإلا قد يتم حظر تطبيقك إلى أجل غير مسمى. تضيف المزالج أيضًا تعقيدات غير ضرورية إلى التعليمات البرمجية، مما يجعل الصيانة أكثر صعوبة.

يتيح لك إصدار Espresso إزالة هذه الحلول البديلة غير الموثوقة من اختباراتك، وتسجيل العمل غير المتزامن لتطبيقك كموارد ثابتة بدلاً من ذلك.

حالات الاستخدام الشائعة

عند إجراء عمليات مشابهة للأمثلة التالية في اختباراتك، ضع في اعتبارك استخدام مورد عدم النشاط:

  • تحميل البيانات من الإنترنت أو من مصدر بيانات محلي
  • إنشاء عمليات ربط بقواعد البيانات وعمليات معاودة الاتصال
  • إدارة الخدمات، إمّا باستخدام خدمة نظام أو مثيل من IntentService.
  • تنفيذ منطق عمل معقد، مثل تحويل الصور النقطية.

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

مثال على تنفيذ موارد عدم النشاط

توضِّح القائمة التالية العديد من الأمثلة على عمليات تنفيذ الموارد غير النشطة التي يمكنك دمجها في تطبيقك:

CountingIdlingResource
الاحتفاظ بعدّاد للمهام النشطة. عندما يكون العدّاد صفرًا، يعتبر المورد المرتبط خاملاً. وتشبه هذه الوظيفة إلى حدّ كبير وظيفة Semaphore. وفي معظم الحالات، تكون عملية التنفيذ هذه كافية لإدارة العمل غير المتزامن لتطبيقك أثناء الاختبار.
UriIdlingResource
مشابهة لـ CountingIdlingResource، ولكن يجب أن يكون العدّاد صفرًا لمدة زمنية محددة قبل أن يتم اعتبار المورد غير نشط. تأخذ فترة الانتظار الإضافية هذه في الاعتبار طلبات الشبكات المتتالية، حيث قد يقدّم أحد التطبيقات ضمن سلسلة المحادثات طلبًا جديدًا فور تلقّي ردّ على طلب سابق.
IdlingThreadPoolExecutor
تنفيذ مخصّص لـ ThreadPoolExecutor يتتبّع إجمالي عدد المهام قيد التشغيل ضمن مجموعات سلاسل المحادثات التي تم إنشاؤها. يستخدم هذا الصف CountingIdlingResource للحفاظ على عدّاد المهام النشطة.
IdlingScheduledThreadPoolExecutor
تنفيذ مخصّص لسمة ScheduledThreadPoolExecutor: وهي توفِّر الوظائف والإمكانات نفسها المتوفّرة في فئة IdlingThreadPoolExecutor، ولكن يمكنها أيضًا تتبُّع المهام المُجدوَلة في المستقبل أو المجدولة لتنفيذها بشكلٍ دوري.

إنشاء مورد عدم النشاط

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

إذا نفذت وظائف موارد عدم النشاط الخاصة بك، ضع في اعتبارك أفضل الممارسات التالية، ولا سيما الأولى:

استدعاء عمليات النقل إلى حالة الخمول خارج عمليات التحقّق من عدم النشاط.
بعد أن يصبح تطبيقك غير نشِط لفترة قصيرة، اتصل بـ onTransitionToIdle() خارج أي من عمليات تنفيذ isIdleNow(). بهذه الطريقة، لا تُجري Espresso أي فحص ثانٍ غير ضروري لتحديد ما إذا كان مورد معيّن غير نشِط لفترة قصيرة.

ويوضّح مقتطف الرمز التالي هذه التوصية:

Kotlin

fun isIdle() {
    // DON'T call callback.onTransitionToIdle() here!
}

fun backgroundWorkDone() {
    // Background work finished.
    callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle.

    // Don't do any post-processing work beyond this point. Espresso now
    // considers your app to be idle and moves on to the next test action.
}

Java

public void isIdle() {
    // DON'T call callback.onTransitionToIdle() here!
}

public void backgroundWorkDone() {
    // Background work finished.
    callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle.

    // Don't do any post-processing work beyond this point. Espresso now
    // considers your app to be idle and moves on to the next test action.
}
تسجيل الموارد غير النشطة قبل الحاجة إليها

لا تسري مزايا المزامنة المرتبطة بموارد عدم النشاط إلّا بعد أول استدعاء لـ Espresso لطريقة isIdleNow() لذلك المورد.

تعرض القائمة التالية عدة أمثلة لهذه السمة:

  • إذا سجّلت مورد عدم النشاط باستخدام طريقة تم التعليق عليها باستخدام @Before، يسري مورد عدم النشاط في السطر الأول من كل اختبار.
  • في حال تسجيل مورد عدم النشاط داخل الاختبار، يدخل مورد عدم النشاط إلى حيز التنفيذ أثناء الإجراء التالي المستند إلى Espresso. ويستمر هذا السلوك حتى إذا كان الإجراء التالي في نفس اختبار العبارة التي تسجِّل مورد عدم النشاط.
يمكنك إلغاء تسجيل الموارد غير النشطة بعد الانتهاء من استخدامها.

للحفاظ على موارد النظام، يجب إلغاء تسجيل الموارد الخاملة حالما لا تحتاج إليها مرة أخرى. على سبيل المثال، إذا سجّلت مورد عدم النشاط بطريقة تم التعليق عليها باستخدام @Before، من الأفضل إلغاء تسجيل هذا المورد بطريقة مقابلة لها تعليقات توضيحية باستخدام @After.

استخدِم سجلّ غير نشِط لفترة قصيرة لتسجيل الموارد غير النشطة وإلغاء تسجيلها.

باستخدام هذه الحاوية لموارد عدم النشاط في تطبيقك، يمكنك تسجيل الموارد غير النشطة وإلغاء تسجيلها بشكل متكرر حسب الحاجة مع الحفاظ على سلوك ثابت.

يجب الحفاظ على حالة التطبيق البسيطة فقط ضمن الموارد غير النشطة.

على سبيل المثال، يجب ألا تحتوي موارد عدم النشاط التي يتم تنفيذها وتسجيلها على مراجع لكائنات View.

تسجيل موارد عدم النشاط

يوفر الأسبريسو فئة حاوية يمكنك فيها وضع موارد تطبيقك الخاملة. يُطلق على هذه الفئة اسم IdlingRegistry، وهي أداة مستقلة تقدِّم الحد الأدنى من النفقات العامة على تطبيقك. كما تسمح لك هذه الفئة باتّخاذ الخطوات التالية بهدف تحسين قابلية صيانة التطبيق:

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

دمج الموارد غير النشطة في تطبيقك

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

عند إضافة موارد عدم النشاط إلى تطبيقك، ننصح بشدة بوضع منطق موارد عدم النشاط في التطبيق نفسه وإجراء عمليات التسجيل وإلغاء التسجيل فقط في اختباراتك.

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

الأساليب البديلة

إذا كنت تفضّل عدم استخدام منطق عدم النشاط في رمز الإنتاج بتطبيقك، هناك العديد من استراتيجيات الدمج القابلة للتطبيق الأخرى:

  • أنشئ صيغًا مختلفة للتصميم، مثل نكهات منتجات Gradle، ولا تستخدِم الموارد غير النشطة إلا في إصدار تصحيح الأخطاء الخاص بتطبيقك.
  • استخدِم إطار عمل تضمين التبعية، مثل Dagger، لإدخال الرسم البياني لتبعية الموارد غير النشطة الخاصة بتطبيقك في اختباراتك. إذا كنت تستخدم Dagger 2، يجب أن تنشأ عملية الإدخال نفسها من مكوّن فرعي.
  • نفِّذ موردًا غير نشِط في اختبارات تطبيقك، واعرض الجزء من تنفيذ التطبيق الذي يحتاج إلى مزامنته في تلك الاختبارات.

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

مراجع إضافية

لمزيد من المعلومات حول استخدام Espresso في اختبارات Android، راجع الموارد التالية.

عيّنات