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