דפוסים נפוצים

אתם יכולים לבדוק את אפליקציית Compose באמצעות גישות ודפוסים מוכרים.

בדיקה במקום יחיד

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

זה לא אומר שצריך ליצור רק בדיקות יחידה של ממשק המשתמש. חשוב מאוד גם לבצע בדיקות UI שמתמקדות בחלקים גדולים יותר בממשק המשתמש.

גישה לפעילות ולמשאבים אחרי הגדרת תוכן משלכם

לעיתים קרובות צריך להגדיר את התוכן שנבדק באמצעות 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()

אימות שחזור המצב

חשוב לוודא שהמצב של רכיבי ה-Composes ישוחזר בזמן היצירה מחדש של הפעילות או התהליך. מבצעים את הבדיקות האלה בלי להסתמך על יצירת מחדש של הפעילות באמצעות הכיתה 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 הוא ממשק API לבדיקה בלבד שמאפשר לדמות הגדרות שונות של מכשירים באופן מותאם לשוק המקומי עבור תוכן @Composable שנמצא בבדיקה.

לאובייקט התומך של DeviceConfigurationOverride יש את פונקציות ההרחבה הבאות, שמבטלות את מאפייני התצורה ברמת המכשיר:

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

לדוגמה, הקוד הבא מחיל את ההחרגה DeviceConfigurationOverride.ForcedSize() כדי לשנות את הצפיפות באופן מקומי, ומאלץ את ה-composable של 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")
    }
}

מקורות מידע נוספים

  • בדיקת אפליקציות ב-Android: דף הנחיתה הראשי של בדיקות Android מספק תצוגה רחבה יותר של העקרונות והשיטות הבסיסיים של בדיקות.
  • העקרונות הבסיסיים של הבדיקה: מידע נוסף על המושגים המרכזיים של בדיקת אפליקציות ל-Android.
  • בדיקות מקומיות: אפשר להריץ בדיקות מסוימות באופן מקומי, בתחנת העבודה שלכם.
  • בדיקות אינסטרומנטליות: מומלץ גם להריץ בדיקות אינסטרומנטליות. כלומר, בדיקות שרצות ישירות במכשיר.
  • אינטגרציה רציפה (CI): אינטגרציה רציפה (CI) מאפשרת לשלב את הבדיקות בצינור עיבוד הנתונים של הפריסה.
  • בדיקה של גדלים שונים של מסכים: מכיוון שיש כל כך הרבה מכשירים שזמינים למשתמשים, כדאי לבדוק את האתר בגדלים שונים של מסכים.
  • Espresso: אמנם הוא מיועד לממשקי משתמש מבוססי-תצוגה, אבל הידע של Espresso עדיין יכול לעזור בהיבטים מסוימים של בדיקות הכתיבה.