בדיקת המקטעים

בנושא הזה נסביר איך לכלול בבדיקות ממשקי API שסופקו על ידי framework. שמעריכים את ההתנהגות של כל מקטע.

מקטעים משמשים כקונטיינרים לשימוש חוזר באפליקציה, ומאפשרים להציג את אותה פריסת ממשק משתמש במגוון פעילויות הגדרות פריסה. בהתחשב בגיוון של מקטעים, חשוב כדי לוודא שהם מספקים חוויה עקבית וחסכונית במשאבים. שימו לב:

  • המקטע לא יכול להיות תלוי בפעילות הורה ספציפית, או מקטע.
  • אין ליצור היררכיית תצוגה של שבר, אלא אם המקטע גלוי למשתמש.

כדי לעזור בהגדרת התנאים לביצוע הבדיקות האלה, AndroidX הספרייה fragment-testing מספקת FragmentScenario ליצור מקטעים ולשנות אותם Lifecycle.State.

הצהרה על יחסי תלות

כדי להשתמש ב-FragmentScenario, צריך להגדיר את הארטיפקט fragment-testing-manifest ב- את קובץ build.gradle של האפליקציה באמצעות debugImplementation, ואת פריט המידע שנוצר בתהליך הפיתוח (Artifact) של fragment-testing באמצעות androidTestImplementation, כמו שמוצג בדוגמה הבאה:

מגניב

dependencies {
    def fragment_version = "1.8.2"

    debugImplementation "androidx.fragment:fragment-testing-manifest:$fragment_version"

    androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version"
}

Kotlin

dependencies {
    val fragment_version = "1.8.2"

    debugImplementation("androidx.fragment:fragment-testing-manifest:$fragment_version")

    androidTestImplementation("androidx.fragment:fragment-testing:$fragment_version")
}

דוגמאות לבדיקה בדף הזה מתבססות על טענות נכונות (assertions) של אספרסו וגם ספריות האמת. לקבלת מידע על ספריות זמינות אחרות של בדיקות וטענות נכונות (assertions), Set up project for AndroidX Test (הגדרת פרויקט לבדיקת AndroidX).

יצירת מקטע

FragmentScenario כולל את השיטות הבאות להפעלת מקטעים בבדיקות:

  • launchInContainer() לבדיקת ממשק המשתמש של חלק. FragmentScenario מצרף את הקובץ מקטע לבקר תצוגה בסיסית של פעילות. כוללת את הפעילות אחרת ריקה.
  • launch() לבדיקה בלי ממשק המשתמש של המקטע. FragmentScenario מצרף מקטע מהסוג הזה לפעילות ריקה, שלא יש תצוגה ברמה הבסיסית (root).

אחרי הפעלה של אחד מסוגי המקטעים האלה, FragmentScenario מפעיל את בבדיקה למצב שצוין. כברירת מחדל, המצב הזה הוא RESUMED, אבל אפשר לשנות זאת באמצעות הארגומנט initialState. מדינת RESUMED מציין שהמקטע פועל וגלוי למשתמש. אפשר לבדוק מידע על הרכיבים בממשק המשתמש באמצעות Espresso UI בדיקות.

דוגמאות הקוד הבאות מראות איך להפעיל את המקטע באמצעות כל אחת מהשיטות:

דוגמה ל-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
        ...
    }
}

אם צריך לקרוא ל-method בקטע עצמו, למשל תגובה לבחירה בתפריט האפשרויות, אפשר לעשות זאת בבטחה על ידי הפניה למקטע באמצעות 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())
    }
}