בנושא הזה נסביר איך לכלול בבדיקות ממשקי API שסופקו על ידי framework. שמעריכים את ההתנהגות של כל מקטע.
מקטעים משמשים כקונטיינרים לשימוש חוזר באפליקציה, ומאפשרים להציג את אותה פריסת ממשק משתמש במגוון פעילויות הגדרות פריסה. בהתחשב בגיוון של מקטעים, חשוב כדי לוודא שהם מספקים חוויה עקבית וחסכונית במשאבים. שימו לב:
- המקטע לא יכול להיות תלוי בפעילות הורה ספציפית, או מקטע.
- אין ליצור היררכיית תצוגה של שבר, אלא אם המקטע גלוי למשתמש.
כדי לעזור בהגדרת התנאים לביצוע הבדיקות האלה, AndroidX
הספרייה fragment-testing
מספקת
FragmentScenario
ליצור מקטעים ולשנות אותם
Lifecycle.State
.
הצהרה על יחסי תלות
כדי להשתמש ב-FragmentScenario
, צריך להגדיר את הארטיפקט fragment-testing-manifest
ב-
את קובץ build.gradle
של האפליקציה באמצעות debugImplementation
, ואת פריט המידע שנוצר בתהליך הפיתוח (Artifact) של fragment-testing
באמצעות androidTestImplementation
, כמו שמוצג
בדוגמה הבאה:
Groovy
dependencies { def fragment_version = "1.8.5" debugImplementation "androidx.fragment:fragment-testing-manifest:$fragment_version" androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version" }
Kotlin
dependencies { val fragment_version = "1.8.5" 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())
}
}