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

يمكنك اختبار تطبيق 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 يمكن أن يكون مفيدًا في بعض جوانب اختبار Compose.