אתם יכולים לבדוק את אפליקציית Compose באמצעות גישות ודפוסים מבוססים.
בדיקה בנפרד
ComposeTestRule מאפשר לכם להתחיל Activity שמציגה כל פונקציה קומפוזבילית: האפליקציה המלאה, מסך בודד או רכיב קטן. כדאי גם לוודא שהרכיבים הניתנים ליצירה מוגדרים בצורה נכונה ופועלים באופן עצמאי, כדי שיהיה קל יותר לבצע בדיקות ממוקדות של ממשק המשתמש.
זה לא אומר שצריך ליצור רק בדיקות יחידה של ממשק המשתמש. חשוב מאוד גם לבצע בדיקות של ממשק המשתמש שכוללות חלקים גדולים יותר של ממשק המשתמש.
גישה לפעילות ולמשאבים אחרי הגדרת תוכן משלכם
במקרים רבים צריך להגדיר את התוכן שנבדק באמצעות 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
עכשיו משתמשים במאפיין הזה ב-modifier 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()
אימות שחזור המצב
מוודאים שהמצב של רכיבי Compose משוחזר בצורה נכונה כשהפעילות או התהליך נוצרים מחדש. כדי לבצע בדיקות כאלה בלי להסתמך על יצירה מחדש של פעילות, משתמשים במחלקה 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.DarkMode(): משנה את הגדרת המערכת לעיצוב כהה או לעיצוב בהיר. -
DeviceConfigurationOverride.FontScale(): משנה את קנה המידה של גופן המערכת. -
DeviceConfigurationOverride.FontWeightAdjustment(): משנה את עובי הגופן שהוגדר במערכת. DeviceConfigurationOverride.ForcedSize(): מאלץ כמות ספציפית של מקום, בלי קשר לגודל המכשיר.-
DeviceConfigurationOverride.LayoutDirection(): משנה את כיוון הפריסה (משמאל לימין או מימין לשמאל). -
DeviceConfigurationOverride.Locales(): משנה את השפה. -
DeviceConfigurationOverride.RoundScreen(): משמש לשינוי אם המסך עגול.
כדי להחיל שינוי ספציפי, צריך לעטוף את התוכן שנבדק בקריאה לפונקציה DeviceConfigurationOverride() ברמה העליונה, ולהעביר את השינוי שרוצים להחיל כפרמטר.
לדוגמה, הקוד הבא מחיל את השינוי מברירת המחדל של DeviceConfigurationOverride.ForcedSize() כדי לשנות את הדחיסות באופן מקומי, ומאלץ את הפונקציה הקומפוזבילית של 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") } }
טיפול מותאם אישית בכשלים בבדיקות
כדי לנפות באגים בבדיקות של ממשק המשתמש, לעיתים קרובות צריך לבדוק את מצב המסך ואת היררכיית הקומפוזיציה כשהטענה הנכונה (assertion) נכשלת.
ב-Compose יש צינור עיבוד נתונים מובנה לטיפול בכשלים, שמאפשר לייעל את תהליך האבחון. אתם יכולים לצלם באופן אוטומטי צילומי מסך והיררכיות של ממשק המשתמש במקרה של כשל, או לרשום רכיבי handler בהתאמה אישית כדי להעביר נתוני טלמטריה של קריסות לכלים חיצוניים.
הגדרת הטיפול בכשלים
כדי להגדיר את הטיפול בכשלים, מעבירים אובייקט TestFailurePolicy אל ComposeUiTestConfig.
תיעוד פריטי מידע מובנים שנוצרו כתוצאה מכשלים
כדי ליצור צילומי מסך והיררכיות של ממשק המשתמש במקרה של שגיאת בדיקה, מגדירים את המאפיינים screenshotCaptureMode ו-uiHierarchyCaptureMode בקובץ TestFailurePolicy.
class MyComposeTest { private val customConfig = ComposeUiTestConfig( failurePolicy = TestFailurePolicy( screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled, uiHierarchyCaptureMode = TestFailurePolicy.CaptureMode.Enabled ) ) @Test fun myFirstTest() = runComposeUiTest(config = customConfig) { // ... } }
שימוש ב-failure handler מותאם אישית
כדי להגדיר התנהגות מותאמת אישית לשגיאות בדיקה, מוסיפים TestFailureHandler לרשימה failureHandlers. כל handler מקבל אובייקט FailureContext שמכיל את השגיאה המקורית ורשימה של פריטי מידע שנוצרו על ידי ה-handlers הקודמים בצינור עיבוד הנתונים.
class MyComposeTestWithHandler { private val customConfig = ComposeUiTestConfig( failurePolicy = TestFailurePolicy( screenshotCaptureMode = TestFailurePolicy.CaptureMode.Enabled, failureHandlers = listOf( TestFailureHandler { context -> val screenshot = context.artifacts.firstOrNull { it.type == FailureArtifact.Type.Screenshot } // ... } ) ) ) @get:Rule val rule = createComposeRule(config = customConfig) // ... }
הגדרת תיעודים לכל חבילת המקרים לבדיקה
כדי להפעיל תיעוד של פריטי מידע שנוצרו כתוצאה מכשלים בכל חבילת המקרים לבדיקה, צריך להעביר ארגומנטים של כלי הרצה של אינסטרומנטציה בקובץ build.gradle של המודול. כך לא צריך לעדכן קובצי בדיקה נפרדים.
// build.gradle.kts
android {
defaultConfig {
// ...
testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isUiHierarchyCaptureEnabled"] = "true"
testInstrumentationRunnerArguments["androidx.compose.ui.test.failure.isScreenshotCaptureEnabled"] = "true"
}
}
סדר הקדימויות של ההגדרות
ה-framework מעריכה גם את הארגומנטים המקומיים של TestFailurePolicy וגם את הארגומנטים של ה-runner ברמת החבילה:
- אם מגדירים מצב באופן מפורש ל-
CaptureMode.Enabled/DisabledבבדיקהfailurePolicy, זה מבטל את הארגומנט של ה-runner. - אם מגדירים מצב ל-
CaptureMode.Unspecified(או משאירים אתfailurePolicyכ-null), המסגרת חוזרת לארגומנט של ה-runner.
מקורות מידע נוספים
- בדיקת אפליקציות ב-Android: דף הנחיתה הראשי של בדיקות ב-Android מספק תצוגה רחבה יותר של העקרונות והשיטות לבדיקה.
- יסודות הבדיקה: מידע נוסף על מושגי הליבה של בדיקת אפליקציה ל-Android.
- בדיקות מקומיות: אתם יכולים להריץ בדיקות מסוימות באופן מקומי, בתחנת העבודה שלכם.
- בדיקות אינסטרומנטציה: מומלץ להריץ גם בדיקות אינסטרומנטציה. כלומר, בדיקות שפועלות ישירות במכשיר.
- אינטגרציה רציפה (CI): אינטגרציה רציפה מאפשרת לכם לשלב את הבדיקות בצינור עיבוד הנתונים לפריסה.
- בדיקה של גדלי מסך שונים: יש כל כך הרבה מכשירים זמינים למשתמשים, לכן כדאי לבדוק גדלי מסך שונים.
- Espresso: למרות שהכלי הזה מיועד לממשקי משתמש שמבוססים על תצוגות, הידע ב-Espresso עדיין יכול לעזור בהיבטים מסוימים של בדיקות ב-Compose.