اختبار أنشطة تطبيقاتك

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

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

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

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

أنشطة الاختبار في Compose

عند اختبار تطبيق تم إنشاؤه باستخدام Jetpack Compose، يمكنك عادةً استخدام createAndroidComposeRule لتشغيل نشاطك والتفاعل مع مكوّنات واجهة المستخدم.

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

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

@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()

@Test fun testEvent() {
    val scenario = composeTestRule.activityRule.scenario

    // ...
}

تحديد حالة النشاط

أحد الجوانب الرئيسية لاختبار أنشطة تطبيقك هو وضع أنشطة تطبيقك في حالات معيّنة. لتحديد الجزء "المعطى" من الاختبارات، استخدِم مثيلات ActivityScenario، وهو جزء من مكتبة AndroidX Test. باستخدام هذه الفئة، يمكنك وضع نشاطك في حالات تحاكي الأحداث على مستوى الجهاز.

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

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

إنشاء نشاط

لإنشاء النشاط قيد الاختبار، أضِف الرمز البرمجي الموضّح في المقتطف التالي:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
       launchActivity<MyActivity>().use {
       }
    }
}

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

تنصح Google باستدعاء close في النشاط عند اكتمال الاختبار. يؤدي ذلك إلى تنظيف الموارد المرتبطة وتحسين ثبات اختباراتك. تنفِّذ ActivityScenario Closeable، لذا يمكنك تطبيق إضافة use ليتم إغلاق النشاط تلقائيًا.

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

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @Test fun testEvent() {
        val scenario = composeTestRule.activityRule.scenario
    }
}

توجيه النشاط إلى حالة جديدة

لنقل النشاط إلى حالة مختلفة، مثل CREATED أو STARTED، استخدِم الدالة moveToState. يحاكي هذا الإجراء حالة يتم فيها إيقاف نشاطك أو إيقافه مؤقتًا، على التوالي، بسبب مقاطعة تطبيق آخر أو إجراء نظام.

يظهر مثال على استخدام moveToState في مقتطف الرمز التالي:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.moveToState(State.CREATED)
        }
    }
}

تحديد حالة النشاط الحالية

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

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.onActivity { activity ->
              startActivity(Intent(activity, MyOtherActivity::class.java))
            }

            val originalActivityState = scenario.state
        }
    }
}

إعادة إنشاء النشاط

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

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.recreate()
        }
    }
}

يحتفظ الصف ActivityScenario بحالة المثيل المحفوظ للنشاط وأي عناصر تمّت إضافة تعليقات توضيحية إليها باستخدام @NonConfigurationInstance. يتم تحميل هذه العناصر في النسخة الجديدة من النشاط قيد الاختبار.

استرداد نتائج النشاط

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

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @Test fun testResult() {
        composeTestRule.onNodeWithTag("finish_button").performClick()

        val scenario = composeTestRule.activityRule.scenario
        val resultCode = scenario.result.resultCode
        val resultData = scenario.result.resultData
    }
}

إجراءات التشغيل في النشاط

جميع الطرق ضِمن ActivityScenario هي عمليات حظر، لذا تتطلّب واجهة برمجة التطبيقات منك تنفيذها في سلسلة تعليمات الأجهزة.

لتنفيذ إجراءات في النشاط قيد الاختبار، استخدِم واجهات برمجة التطبيقات الخاصة بالاختبار في Compose للتفاعل مع العناصر القابلة للإنشاء:

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MyActivity>()

    @Test fun testEvent() {
        composeTestRule.onNodeWithText("Refresh").performClick()
    }
}

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

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @Test fun testEvent() {
        launchActivity<MyActivity>().use { scenario ->
            scenario.onActivity { activity ->
              activity.handleSwipeToRefresh()
            }
        }
    }
}

مراجع إضافية

لمزيد من المعلومات حول الاختبار، يُرجى الاطّلاع على المراجع الإضافية التالية:

الوثائق