أساسيات اختبار تطبيقات Android

تحدد هذه الصفحة المبادئ الأساسية لاختبار تطبيقات Android، بما في ذلك أفضل الممارسات المركزية وفوائدها.

مزايا الاختبار

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

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

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

أنواع الاختبارات في نظام Android

تعد التطبيقات المتوافقة مع الأجهزة الجوّالة معقدة ويجب أن تعمل بشكل جيد في العديد من البيئات. وعلى هذا النحو، هناك أنواع عديدة من الاختبارات.

الموضوع

على سبيل المثال، تتوفّر أنواع مختلفة من الاختبارات استنادًا إلى الموضوع:

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

المجال

تختلف الاختبارات أيضًا حسب الحجم أو درجة العزل:

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

هناك العديد من الطرق لتصنيف الاختبارات. إلا أن أهم ما يميز مطوّري التطبيقات هو مكان إجراء الاختبارات.

الاختبارات الآلية مقابل الاختبارات المحلية

يمكنك إجراء الاختبارات على جهاز Android أو على كمبيوتر آخر:

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

لا يتم إجراء جميع اختبارات الوحدات على الجهاز، كما لا يتم إجراء جميع الاختبارات الشاملة على الجهاز. على سبيل المثال:

  • الاختبار المحلي الكبير: يمكنك استخدام محاكي Android الذي يتم تشغيله محليًا، مثل Robolectric.
  • اختبار الأدوات الصغيرة: يمكنك التأكّد من أنّ الرمز البرمجي يعمل بشكل جيد مع ميزة إطار العمل، مثل قاعدة بيانات SQLite. يمكنك إجراء هذا الاختبار على أجهزة متعددة للتحقق من التكامل مع إصدارات متعددة من SQLite.

أمثلة

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

اسبريسو

// When the Continue button is clicked
onView(withText("Continue"))
    .perform(click())

// Then the Welcome screen is displayed
onView(withText("Welcome"))
    .check(matches(isDisplayed()))

إنشاء واجهة المستخدم

// When the Continue button is clicked
composeTestRule.onNodeWithText("Continue").performClick()

// Then the Welcome screen is displayed
composeTestRule.onNodeWithText("Welcome").assertIsDisplayed()

يعرض هذا المقتطف جزءًا من اختبار وحدة لنموذج ViewModel (اختبار محلي، من جهة المضيف):

// Given an instance of MyViewModel
val viewModel = MyViewModel(myFakeDataRepository)

// When data is loaded
viewModel.loadData()

// Then it should be exposing data
assertTrue(viewModel.data != null)

تحديد استراتيجية الاختبار

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

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

اختبارات غير مستقرة

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

بنية قابلة للاختبار

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

ينتج عن البنية غير القابلة للاختبار ما يلي:

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

لمعرفة المزيد من المعلومات حول إرشادات البنية، يمكنك الاطّلاع على دليل بنية التطبيق.

أساليب إلغاء الاقتران

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

تتضمن أساليب الفصل الشائعة ما يلي:

  • تقسيم تطبيق إلى طبقات، مثل العرض التقديمي والنطاق والبيانات. يمكنك أيضًا تقسيم تطبيق إلى وحدات، واحدة لكل ميزة.
  • تجنَّب إضافة المنطق إلى الكيانات التي لها تبعيات كبيرة، مثل الأنشطة والأجزاء. استخدِم هذه الفئات كنقاط دخول إلى إطار العمل وانقل واجهة المستخدم ومنطق العمل إلى مكان آخر، مثل طبقة مركّبة أو ViewModel أو طبقة نطاق.
  • تجنَّب تبعيات إطار العمل المباشرة في الصفوف التي تتضمّن منطق العمل. على سبيل المثال، لا تستخدم سياقات Android في ViewModels.
  • سهِّل استبدال التبعيات. على سبيل المثال، استخدِم الواجهات بدلاً من عمليات التنفيذ الملموسة. استخدِم إدخال التبعية حتى إذا كنت لا تستخدم إطار عمل DI.

الخطوات التالية

والآن بعد أن عرفت الأسباب التي تدفعك إلى الاختبار والنوعين الرئيسيين من الاختبارات، يمكنك قراءة ما يجب اختباره.

أما إذا أردت إنشاء الاختبار الأول والتعلّم من خلال التنفيذ، فاطّلع على الدروس التطبيقية لاختبار الترميز.