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

يمكنك اختبار تطبيق 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()

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

تأكَّد من استعادة حالة عناصر الإنشاء بشكل صحيح عند إعادة إنشاء النشاط أو العملية. يمكنك إجراء عمليات التحقّق هذه بدون الاعتماد على إعادة إنشاء النشاط باستخدام فئة 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.