אתם יכולים לבדוק את אפליקציית Compose באמצעות גישות ודפוסים מבוססים.
בדיקה בבידוד
ComposeTestRule מאפשרת להתחיל פעילות שמציגה כל רכיב שאפשר להרכיב: את האפליקציה המלאה, מסך יחיד או רכיב קטן. מומלץ גם לוודא שהרכיבים הניתנים להרכבה מבודדים בצורה נכונה ושהם פועלים באופן עצמאי, כדי שיהיה קל יותר לבצע בדיקות ממוקדות של ממשק המשתמש.
זה לא אומר שצריך ליצור רק בדיקות יחידה של ממשק המשתמש. חשוב גם להגדיר את היקף הבדיקות של ממשק המשתמש לחלקים גדולים יותר של ממשק המשתמש.
גישה לפעילות ולמשאבים אחרי הגדרת התוכן שלכם
לעתים קרובות צריך להגדיר את התוכן שנבדק באמצעות 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()
אימות שחזור המצב
מוודאים שהמצב של רכיבי ה-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") } }
טיפול בכשלים בבדיקות בהתאמה אישית
כדי לנפות באגים בבדיקות של ממשק המשתמש, צריך לעיתים קרובות לבדוק את מצב המסך ואת היררכיית הקומפוזיציה כשטענה נכשלת.
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) { // ... } }
שימוש בטיפול מותאם אישית בשגיאות
כדי להגדיר התנהגות מותאמת אישית לכישלונות בבדיקות, מוסיפים TestFailureHandler לרשימה failureHandlers. כל רכיב handler מקבל אובייקט FailureContext שמכיל את השגיאה המקורית ורשימה של ארטיפקטים שנוצרו על ידי רכיבי ה-handler הקודמים בצינור.
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"
}
}
קדימות של הגדרות
המסגרת מעריכה גם את הארגומנטים של הרצת הבדיקות ברמה המקומית TestFailurePolicy וגם את הארגומנטים של הרצת הבדיקות ברמת החבילה:
- אם מגדירים במפורש מצב ל-
CaptureMode.Enabled/DisabledבבדיקהfailurePolicy, ההגדרה הזו מבטלת את הארגומנט של הרצת הבדיקה. - אם מגדירים מצב ל-
CaptureMode.Unspecified(או משאירים אתfailurePolicyכ-null), המסגרת חוזרת לארגומנט של הרצת הבדיקה.
מקורות מידע נוספים
- בדיקת אפליקציות ב-Android: דף הנחיתה הראשי בנושא בדיקות ב-Android מספק סקירה רחבה יותר של עקרונות וטכניקות בדיקה.
- יסודות הבדיקה: מידע נוסף על המושגים הבסיסיים שמאחורי בדיקת אפליקציה ל-Android.
- בדיקות מקומיות: אתם יכולים להריץ בדיקות מסוימות באופן מקומי, בתחנת העבודה שלכם.
- בדיקות עם מכשור: מומלץ להריץ גם בדיקות עם מכשור. כלומר, בדיקות שמופעלות ישירות במכשיר.
- אינטגרציה רציפה (CI): אינטגרציה רציפה מאפשרת לכם לשלב את הבדיקות שלכם בצינור הפריסה.
- בדיקה של גדלי מסך שונים: יש למשתמשים הרבה מכשירים שונים, ולכן כדאי לבדוק גדלי מסך שונים.
- Espresso: למרות שהיא מיועדת לממשקי משתמש מבוססי-תצוגה, הידע ב-Espresso עדיין יכול לעזור בחלק מההיבטים של בדיקות ב-Compose.