يمكنك اختبار تطبيق 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") } }
معالجة حالات الفشل المخصّصة في الاختبارات
يتطلّب تصحيح أخطاء اختبارات واجهة المستخدم غالبًا فحص حالة الشاشة والتسلسل الهرمي لإنشاء واجهة المستخدم عند تعذُّر تنفيذ تأكيد.
يوفّر Compose مسارًا مدمجًا لمعالجة حالات التعطُّل من أجل تبسيط عمليات التشخيص. يمكنك التقاط لقطات شاشة وتسلسلات هرمية لواجهة المستخدم تلقائيًا عند حدوث عطل، أو تسجيل معالِجات مخصّصة لإعادة توجيه بيانات قياس الأعطال إلى أدوات خارجية.
ضبط معالجة حالات الفشل
لضبط معالجة حالات تعذُّر التحميل، مرِّر عنصر TestFailurePolicy إلى
ComposeUiTestConfig.
التقاط عناصر الفشل المضمّنة
لالتقاط لقطات شاشة وتسلسلات هرمية لواجهة المستخدم عند تعذّر الاختبار، اضبط السمتَين screenshotCaptureMode وuiHierarchyCaptureMode في TestFailurePolicy.
class MyComposeTest { private val customConfig = ComposeUiTestConfig( failurePolicy = TestFailurePolicy( screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled, uiHierarchyCaptureMode = TestFailurePolicy.CaptureMode.Enabled ) ) @Test fun myFirstTest() = runComposeUiTest(config = customConfig) { // ... } }
استخدام معالج إخفاق مخصّص
لتحديد سلوك مخصّص لحالات تعذُّر الاختبار، أضِف
TestFailureHandler إلى قائمة failureHandlers. يتلقّى كل معالج عنصر FailureContext يحتوي على الخطأ الأصلي وقائمة بالعناصر التي تم إنشاؤها بواسطة معالجات المسار السابقة.
class MyComposeTestWithHandler { private val customConfig = ComposeUiTestConfig( failurePolicy = TestFailurePolicy( screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled, failureHandlers = listOf( TestFailureHandler { context -> val screenshot = context.artifacts.firstOrNull { it.type == FailureArtifact.Type.Screenshot } // ... } ) ) ) @get:Rule val rule = createComposeRule(config = customConfig) // ... }
ضبط عمليات التسجيل لحزمة اختبارية كاملة
يمكنك تفعيل عمليات التقاط عناصر الإخفاق لحزمة اختبارية كاملة من خلال تمرير
وسيطات مشغّل قياس حالة التطبيق في ملف build.gradle الخاص بالوحدة. وهذا يلغي الحاجة إلى تحديث ملفات الاختبار الفردية.
// build.gradle.kts
android {
defaultConfig {
// ...
testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isUiHierarchyCaptureEnabled"] = "true"
testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isScreenshotCaptureEnabled"] = "true"
}
}
أولوية الإعدادات
يقيّم إطار العمل كلاً من وسيطات المشغّل المحلية TestFailurePolicy وعلى مستوى المجموعة:
- إذا ضبطت وضعًا صراحةً على
CaptureMode.Enabled/Disabledفي اختبارfailurePolicy، سيؤدي ذلك إلى إلغاء وسيطة المشغّل. - في حال ضبط وضع على
CaptureMode.Unspecified(أو تركfailurePolicyعلى النحو التالي:null)، يعود إطار العمل إلى وسيطة المشغّل.
موارد إضافية
- اختبار التطبيقات على Android: توفّر الصفحة المقصودة الرئيسية لاختبار تطبيقات Android نظرة أوسع على أساسيات الاختبار وأساليبه.
- أساسيات الاختبار: يمكنك الاطّلاع على مزيد من المعلومات حول المفاهيم الأساسية لاختبار تطبيق Android.
- الاختبارات المحلية: يمكنك إجراء بعض الاختبارات محليًا على محطة العمل الخاصة بك.
- اختبارات لقياس حالة التطبيق: من الممارسات الجيدة أيضًا إجراء اختبارات لقياس حالة التطبيق. أي الاختبارات التي يتم إجراؤها مباشرةً على الجهاز.
- التكامل المستمر: يتيح لك التكامل المستمر دمج اختباراتك في مسار النشر.
- اختبار أحجام الشاشات المختلفة: نظرًا لتوفّر العديد من الأجهزة للمستخدمين، يجب إجراء اختبارات لأحجام الشاشات المختلفة.
- Espresso: على الرغم من أنّ Espresso مُصمَّمة لواجهات المستخدم المستندة إلى العرض، إلا أنّ معرفة أدوات Espresso يمكن أن تكون مفيدة في بعض جوانب اختبار Compose.