يوضِّح هذا الموضوع كيفية تضمين واجهات برمجة التطبيقات المقدَّمة من إطار العمل في الاختبارات. لتقييم سلوك كل جزء.
تعمل الأجزاء كحاويات قابلة لإعادة الاستخدام داخل تطبيقك، ما يتيح لك تقديم نفس تخطيط واجهة المستخدم في مجموعة متنوعة من الأنشطة عمليات تهيئة التخطيطات. وبالنظر إلى تنوع الأجزاء، من المهم للتحقق من أنها تقدم تجربة متسقة وفعالة من حيث استخدام الموارد. ملاحظات:
- كما يجب ألا يعتمد الجزء على نشاط رئيسي محدد أو .
- يجب عدم إنشاء عرض هرمي للجزء ما لم يتم إنشاء الجزء مرئية للمستخدم.
للمساعدة في إعداد شروط إجراء هذه الاختبارات، يستخدم نظام AndroidX
توفّر مكتبة fragment-testing
FragmentScenario
لإنشاء أجزاء وتغيير
Lifecycle.State
إعلان التبعيات
لاستخدام FragmentScenario
، يجب تحديد عنصر fragment-testing-manifest
في
ملف build.gradle
في التطبيق باستخدام debugImplementation
، وعناصر fragment-testing
التي تستخدم androidTestImplementation
كما هو موضَّح في
المثال التالي:
Groovy
dependencies { def fragment_version = "1.8.3" debugImplementation "androidx.fragment:fragment-testing-manifest:$fragment_version" androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version" }
Kotlin
dependencies { val fragment_version = "1.8.3" debugImplementation("androidx.fragment:fragment-testing-manifest:$fragment_version") androidTestImplementation("androidx.fragment:fragment-testing:$fragment_version") }
تستخدم أمثلة الاختبار في هذه الصفحة تأكيدات من Espresso مكتبات Truth للحصول على معلومات عن مكتبات الاختبار والتأكيد الأخرى المتاحة، راجع إعداد المشروع لاختبار AndroidX
إنشاء جزء
يتضمّن FragmentScenario
الطرق التالية لتشغيل الأجزاء.
في الاختبارات:
launchInContainer()
، لاختبار واجهة المستخدم للجزء يُرفِقFragmentScenario
إلى وحدة التحكم في العرض الجذري للنشاط. يحتوي هذا القسم على النشاط. فارغة بخلاف ذلك.launch()
، للاختبار بدون واجهة مستخدم الجزء.FragmentScenario
تُرفِق هذا النوع من الأجزاء بنشاط فارغ، أي نشاط لا طريقة عرض الجذر.
بعد تشغيل أحد أنواع الأجزاء هذه، تعمل FragmentScenario
على زيادة
قيد الاختبار إلى حالة محددة. وبشكلٍ تلقائي، هذه الولاية هي RESUMED
،
ولكن يمكنك إلغاء هذا باستخدام الوسيطة initialState
. ولاية RESUMED
إلى أن الجزء قيد التشغيل ومرئي للمستخدم. يمكنك تقييم
معلومات حول عناصر واجهة المستخدم باستخدام واجهة مستخدم Espresso
الاختبارات.
توضح أمثلة التعليمات البرمجية التالية كيفية تشغيل الجزء باستخدام كل طريقة:
مثال على launchInContainer()
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
// The "fragmentArgs" argument is optional.
val fragmentArgs = bundleOf(“selectedListItem” to 0)
val scenario = launchFragmentInContainer<EventFragment>(fragmentArgs)
...
}
}
مثال على()launch
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
// The "fragmentArgs" arguments are optional.
val fragmentArgs = bundleOf("numElements" to 0)
val scenario = launchFragment<EventFragment>(fragmentArgs)
...
}
}
تقديم التبعيات
إذا كانت الأجزاء تابعة لك، فيمكنك توفير إصدارات اختبارية من
هذه الاعتماديات من خلال توفير FragmentFactory
مخصّص
الطريقة launchInContainer()
أو launch()
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val someDependency = TestDependency()
launchFragmentInContainer {
EventFragment(someDependency)
}
...
}
}
لمزيد من المعلومات حول استخدام FragmentFactory
لتقديم
والتبعيات إلى الأجزاء، انظر
مدير التجزئة:
نقل الجزء إلى حالة جديدة
في اختبارات واجهة المستخدم في تطبيقك، يكفي عادةً بدء الجزء
قيد الاختبار وبدء الاختبار من حالة RESUMED
. أكثر دقة
لاختبار الوحدة، يمكنك أيضًا تقييم سلوك الجزء
أثناء انتقالها من حالة دورة حياة إلى أخرى. يمكنك تحديد
من خلال تمرير وسيطة initialState
إلى أي من
دوال launchFragment*()
.
لنقل الجزء إلى حالة دورة حياة مختلفة، اطلب
moveToState()
تتيح هذه الطريقة استخدام الحالات التالية كوسيطات: CREATED
,
STARTED
وRESUMED
وDESTROYED
هذه الطريقة تحاكي موقفًا
عندما يتغيّر الجزء أو النشاط الذي يحتوي على الجزء
لأي سبب من الأسباب.
يفتح المثال التالي جزءًا اختباريًا في الحالة INITIALIZED
ثم نقله إلى حالة RESUMED
:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>(
initialState = Lifecycle.State.INITIALIZED
)
// EventFragment has gone through onAttach(), but not onCreate().
// Verify the initial state.
scenario.moveToState(Lifecycle.State.RESUMED)
// EventFragment moves to CREATED -> STARTED -> RESUMED.
...
}
}
إعادة إنشاء الجزء
إذا كان تطبيقك يعمل على جهاز منخفضة الموارد، يمكن للنظام
قد يؤدي إلى تدمير النشاط الذي يحتوي على الجزء. هذا الموقف
يتطلب من تطبيقك إعادة إنشاء الجزء عندما يعود المستخدم إليه.
لمحاكاة هذا الموقف، عليك الاتصال بالرقم recreate()
:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
scenario.recreate()
...
}
}
FragmentScenario.recreate()
تدمر الجزء ومضيفه ثم تعيد إنشاؤه. عندما
تعيد الفئة FragmentScenario
إنشاء الجزء قيد الاختبار، أي الجزء
إلى حالة دورة الحياة التي كانت عليه قبل تدميره.
التفاعل مع أجزاء واجهة المستخدم
لتشغيل إجراءات واجهة المستخدم في الجزء قيد الاختبار، استخدم مطابقة عروض الإسبريسو بالتفاعل مع العناصر في طريقة العرض الخاصة بك:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
onView(withId(R.id.refresh)).perform(click())
// Assert some expected behavior
...
}
}
إذا كنت بحاجة إلى استدعاء طريقة على الجزء نفسه، مثل الاستجابة
إلى تحديد ما في قائمة الخيارات، يمكنك إجراء ذلك بأمان من خلال الحصول على
الإشارة إلى الجزء باستخدام
FragmentScenario.onFragment()
ويمر
FragmentAction
:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
scenario.onFragment { fragment ->
fragment.myInstanceMethod()
}
}
}
اختبار إجراءات مربّعات الحوار
يتوافق "FragmentScenario
" أيضًا مع الاختبار.
أجزاء مربّع الحوار. على الرغم من أنّ أجزاء مربّعات الحوار
عناصر واجهة المستخدم، تتم تعبئة تنسيقها في نافذة منفصلة، بدلاً من
عنها في النشاط نفسه. لهذا السبب، استخدم
FragmentScenario.launch()
لاختبار أجزاء مربّعات الحوار.
يختبر المثال التالي عملية إغلاق مربّع الحوار:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testDismissDialogFragment() {
// Assumes that "MyDialogFragment" extends the DialogFragment class.
with(launchFragment<MyDialogFragment>()) {
onFragment { fragment ->
assertThat(fragment.dialog).isNotNull()
assertThat(fragment.requireDialog().isShowing).isTrue()
fragment.dismiss()
fragment.parentFragmentManager.executePendingTransactions()
assertThat(fragment.dialog).isNull()
}
}
// Assumes that the dialog had a button
// containing the text "Cancel".
onView(withText("Cancel")).check(doesNotExist())
}
}