الأنماط الشائعة

يمكنك اختبار تطبيق Compose باستخدام أساليب وأنماط راسخة.

الاختبار بشكل منفصل

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

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

الوصول إلى النشاط والمراجع بعد ضبط المحتوى الخاص بك

في كثير من الأحيان، تحتاج إلى ضبط المحتوى قيد الاختبار باستخدام composeTestRule.setContent، كما تحتاج أيضًا إلى الوصول إلى موارد النشاط، على سبيل المثال، للتأكّد من أنّ النص المعروض يطابق مورد سلسلة. ومع ذلك، لا يمكنك استدعاء setContent في قاعدة تم إنشاؤها باستخدام createAndroidComposeRule() إذا كان النشاط يستدعيها.

يتم عادةً تحقيق ذلك من خلال إنشاء AndroidComposeTestRule باستخدام نشاط فارغ، مثل ComponentActivity.

class MyComposeTest {

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

    @Test
    fun myTest() {
        // Start the app
        composeTestRule.setContent {
            MyAppTheme {
                MainScreen(uiState = exampleUiState, /*...*/)
            }
        }
        val continueLabel = composeTestRule.activity.getString(R.string.next)
        composeTestRule.onNodeWithText(continueLabel).performClick()
    }
}

يُرجى العِلم أنّه يجب إضافة ComponentActivity إلى ملف AndroidManifest.xml في تطبيقك. يمكنك تفعيل ذلك من خلال إضافة التبعية التالية إلى الوحدة:

debugImplementation("androidx.compose.ui:ui-test-manifest:$compose_version")

خصائص الدلالات المخصّصة

يمكنك إنشاء خصائص دلالات مخصّصة لعرض المعلومات للاختبارات. لإجراء ذلك، حدِّد SemanticsPropertyKey جديدًا وأتحه باستخدام SemanticsPropertyReceiver.

// Creates a semantics property of type Long.
val PickedDateKey = SemanticsPropertyKey<Long>("PickedDate")
var SemanticsPropertyReceiver.pickedDate by PickedDateKey

الآن استخدِم هذه السمة في المعدِّل semantics:

val datePickerValue by remember { mutableStateOf(0L) }
MyCustomDatePicker(
    modifier = Modifier.semantics { pickedDate = datePickerValue }
)

من الاختبارات، استخدِم SemanticsMatcher.expectValue لتأكيد قيمة السمة:

composeTestRule
    .onNode(SemanticsMatcher.expectValue(PickedDateKey, 1445378400)) // 2015-10-21
    .assertExists()

التحقّق من استعادة الحالة

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

تتيح لك هذه الفئة محاكاة إعادة إنشاء عنصر قابل للإنشاء. ويفيد ذلك بشكل خاص في التحقّق من تنفيذ rememberSaveable.


class MyStateRestorationTests {

    @get:Rule
    val composeTestRule = createComposeRule()

    @Test
    fun onRecreation_stateIsRestored() {
        val restorationTester = StateRestorationTester(composeTestRule)

        restorationTester.setContent { MainScreen() }

        // TODO: Run actions that modify the state

        // Trigger a recreation
        restorationTester.emulateSavedInstanceStateRestore()

        // TODO: Verify that state has been correctly restored.
    }
}

اختبار إعدادات مختلفة للأجهزة

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

DeviceConfigurationOverride هي واجهة برمجة تطبيقات مخصّصة للاختبار فقط، وتتيح لك محاكاة إعدادات مختلفة للأجهزة بطريقة متوافقة مع اللغة المحلية لمحتوى @Composable قيد الاختبار.

يحتوي العنصر المرافق DeviceConfigurationOverride على دوال الإضافة التالية التي تتجاوز خصائص الإعداد على مستوى الجهاز:

لتطبيق عملية إلغاء محدّدة، عليك تضمين المحتوى الذي يتم اختباره في استدعاء الدالة ذات المستوى الأعلى DeviceConfigurationOverride()، مع تمرير عملية الإلغاء التي سيتم تطبيقها كمعلَمة.

على سبيل المثال، يطبّق الرمز التالي عملية الإلغاء DeviceConfigurationOverride.ForcedSize() لتغيير الكثافة محليًا، ما يؤدي إلى عرض العنصر القابل للإنشاء MyScreen في نافذة كبيرة في الوضع الأفقي، حتى إذا كان الجهاز الذي يتم تشغيل الاختبار عليه لا يتيح حجم النافذة هذا مباشرةً:

composeTestRule.setContent {
    DeviceConfigurationOverride(
        DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp))
    ) {
        MyScreen() // Will be rendered in the space for 1280dp by 800dp without clipping.
    }
}

لتطبيق عمليات إلغاء متعددة معًا، استخدِم DeviceConfigurationOverride.then():

composeTestRule.setContent {
    DeviceConfigurationOverride(
        DeviceConfigurationOverride.FontScale(1.5f) then
            DeviceConfigurationOverride.FontWeightAdjustment(200)
    ) {
        Text(text = "text with increased scale and weight")
    }
}

مراجع إضافية

  • اختبار التطبيقات على Android: تقدّم صفحة Android الرئيسية الخاصة بالاختبار نظرة عامة على أساسيات الاختبار وأساليبه.
  • أساسيات الاختبار: مزيد من المعلومات عن المفاهيم الأساسية لاختبار تطبيق Android
  • الاختبارات المحلية: يمكنك إجراء بعض الاختبارات محليًا على محطة العمل الخاصة بك.
  • الاختبارات المبرمَجة: من الممارسات الجيدة أيضًا إجراء اختبارات مبرمَجة. أي الاختبارات التي يتم إجراؤها مباشرةً على الجهاز.
  • التكامل المستمر: يتيح لك التكامل المستمر دمج اختباراتك في مسار النشر.
  • اختبار أحجام الشاشات المختلفة: بما أنّ المستخدمين يتوفّر لديهم العديد من الأجهزة، عليك اختبار أحجام الشاشات المختلفة.
  • Espresso: على الرغم من أنّ Espresso مخصّصة لواجهات المستخدم المستندة إلى العرض، يمكن أن تكون معرفة Espresso مفيدة في بعض جوانب اختبار Compose.