اختبار الأجزاء غير النشطة

يوضِّح هذا الموضوع كيفية تضمين واجهات برمجة التطبيقات المقدَّمة من إطار العمل في الاختبارات. لتقييم سلوك كل جزء.

تعمل الأجزاء كحاويات قابلة لإعادة الاستخدام داخل تطبيقك، ما يتيح لك تقديم نفس تخطيط واجهة المستخدم في مجموعة متنوعة من الأنشطة عمليات تهيئة التخطيطات. وبالنظر إلى تنوع الأجزاء، من المهم للتحقق من أنها تقدم تجربة متسقة وفعالة من حيث استخدام الموارد. ملاحظات:

  • كما يجب ألا يعتمد الجزء على نشاط رئيسي محدد أو .
  • يجب عدم إنشاء عرض هرمي للجزء ما لم يتم إنشاء الجزء مرئية للمستخدم.

للمساعدة في إعداد شروط إجراء هذه الاختبارات، يستخدم نظام 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())
    }
}