يمكنك اختبار تطبيق 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.DarkMode(): يتجاهل إعدادات النظام ويفرض استخدام المظهر الداكن أو المظهر الفاتح.DeviceConfigurationOverride.FontScale(): تلغي مقياس خط النظام.DeviceConfigurationOverride.FontWeightAdjustment(): تلغي هذه السمة تعديل وزن خط النظام.-
DeviceConfigurationOverride.ForcedSize(): تفرض هذه السمة مقدارًا معيّنًا من المساحة بغض النظر عن حجم الجهاز. DeviceConfigurationOverride.LayoutDirection(): تلغي اتجاه التنسيق (من اليسار إلى اليمين أو من اليمين إلى اليسار).DeviceConfigurationOverride.Locales(): تلغي اللغة.DeviceConfigurationOverride.RoundScreen(): يتم تجاهل هذه السمة إذا كانت الشاشة دائرية.
لتطبيق عملية إلغاء محدّدة، عليك تضمين المحتوى الذي يتم اختباره في استدعاء الدالة ذات المستوى الأعلى
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.