פעילויות משמשות כמאגרים לכל אינטראקציית משתמש באפליקציה, ולכן חשוב לבדוק את ההתנהגות של הפעילויות באפליקציה במהלך אירועים ברמת המכשיר, כמו האירועים הבאים:
- אפליקציה אחרת, כמו אפליקציית הטלפון של המכשיר, קוטעת את הפעילות של האפליקציה שלכם.
- המערכת תמחק את הפעילות ותיצור אותה מחדש.
- המשתמש מציב את הפעילות שלכם בסביבת חלונות חדשה, כמו תמונה בתוך תמונה (PIP) או ריבוי חלונות.
בפרט, חשוב לוודא שהפעילות מתנהלת בצורה נכונה בתגובה לאירועים שמתוארים במאמר מחזור החיים של הפעילות.
במדריך הזה מוסבר איך להעריך את היכולת של האפליקציה לשמור על תקינות נתונים ועל חוויית משתמש טובה, כשפעילויות באפליקציה עוברות בין מצבים שונים במחזור החיים שלהן.
בדיקת פעילויות ב-Compose
כשבודקים אפליקציה שנבנתה באמצעות Jetpack פיתוח נייטיב, בדרך כלל משתמשים ב-createAndroidComposeRule כדי להפעיל את הפעילות ולקיים אינטראקציה עם רכיבי ממשק המשתמש.
עם זאת, כדי לבדוק אירועים ברמת המכשיר, כמו שינויים בהגדרות או פעילות שהועברה לרקע או שהמערכת השביתה אותה, צריך לשנות את מחזור החיים של הפעילות ישירות. כדי לעשות את זה, משתמשים ב-framework הבסיסי ActivityScenario.
כלל הבדיקה Compose עוטף את התרחיש הזה ומנהל אותו בשבילכם באופן אוטומטי. במדריך הזה תראו את התבנית הבאה שמשמשת לגישור על הפער בין בדיקות ממשק משתמש מודרניות לבין ניהול מחזור חיים רגיל:
@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()
@Test fun testEvent() {
val scenario = composeTestRule.activityRule.scenario
// ...
}
הגדרת מצב של פעילות
אחד ההיבטים המרכזיים בבדיקת הפעילויות של האפליקציה הוא הצבת הפעילויות של האפליקציה במצבים מסוימים. כדי להגדיר את החלק הזה של הבדיקות, משתמשים במופעים של ActivityScenario, חלק מהספרייה AndroidX Test. באמצעות המחלקה הזו, אפשר להציב את הפעילות במצבים שמדמים אירועים ברמת המכשיר.
ActivityScenario הוא ממשק API בפלטפורמות שונות שאפשר להשתמש בו בבדיקות יחידה מקומיות ובבדיקות שילוב במכשיר. במכשיר אמיתי או וירטואלי, ActivityScenario מספק בטיחות בשרשור (thread safety) ומסנכרן אירועים בין שרשור האינסטרומנטציה של הבדיקה לבין השרשור שמריץ את הפעילות שנבדקת.
ה-API מתאים במיוחד להערכת ההתנהגות של פעילות שנמצאת בבדיקה כשהיא מושמדת או נוצרת. בקטע הזה מפורטים התרחישים הנפוצים ביותר שקשורים ל-API הזה.
יצירת פעילות
כדי ליצור את הפעילות שנבדקת, מוסיפים את הקוד שמוצג בקטע הקוד הבא:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use {
}
}
}
אחרי שיוצרים את הפעילות, ActivityScenario מעביר את הפעילות למצב RESUMED. הסטטוס הזה מציין שהפעילות שלכם פועלת ושהיא גלויה למשתמשים. במצב הזה, אתם יכולים ליצור אינטראקציה עם רכיבי ה-Composable של הפעילות באמצעות ממשקי ה-API לבדיקה של Compose.
Google ממליצה לקרוא ל-close בפעילות כשהבדיקה מסתיימת.
כך מנקים את המשאבים המשויכים ומשפרים את היציבות של הבדיקות. ActivityScenario implements Closeable, כך שאפשר להחיל את התוסף use
כדי שהפעילות תיסגר אוטומטית.
לחלופין, אפשר להשתמש ב-createAndroidComposeRule כדי להפעיל את הפעילות באופן אוטומטי לפני כל בדיקה, לטפל בפירוק ולתת לכם גישה לשיטות הבדיקה של ממשק המשתמש של Compose ול-ActivityScenario הבסיסי. בדוגמה הבאה אפשר לראות איך מגדירים כלל ומקבלים ממנו מופע של תרחיש:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()
@Test fun testEvent() {
val scenario = composeTestRule.activityRule.scenario
}
}
העברת הפעילות למצב חדש
כדי להעביר את הפעילות למצב אחר, כמו CREATED או STARTED, צריך להתקשר אל moveToState. הפעולה הזו מדמה מצב שבו הפעילות שלכם נעצרת או מושהית, בהתאמה, כי היא מופרעת על ידי אפליקציה אחרת או פעולת מערכת.
דוגמה לשימוש ב-moveToState מופיעה בקטע הקוד הבא:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.moveToState(State.CREATED)
}
}
}
קביעת מצב הפעילות הנוכחי
כדי לקבוע את המצב הנוכחי של פעילות שנבדקת, מקבלים את הערך של השדה state באובייקט ActivityScenario. זה שימושי במיוחד לבדיקת הסטטוס של פעילות שנבדקת אם הפעילות מפנה לפעילות אחרת או מסתיימת בעצמה, כמו שמוצג בקטע הקוד הבא:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.onActivity { activity ->
startActivity(Intent(activity, MyOtherActivity::class.java))
}
val originalActivityState = scenario.state
}
}
}
יצירה מחדש של הפעילות
כשבמכשיר יש מעט משאבים, המערכת עשויה להרוס פעילות, ולכן האפליקציה צריכה ליצור מחדש את הפעילות הזו כשהמשתמש חוזר לאפליקציה. כדי לדמות את התנאים האלה, צריך להתקשר אל recreate:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.recreate()
}
}
}
המחלקות ActivityScenario שומרות את מצב המופע של הפעילות ואת כל האובייקטים שמסומנים באמצעות @NonConfigurationInstance. האובייקטים האלה נטענים למופע החדש של הפעילות שנבדקת.
אחזור תוצאות הפעילות
כדי לקבל את קוד התוצאה או את הנתונים שמשויכים לפעילות שהסתיימה, צריך לקבל את הערך של השדה result באובייקט ActivityScenario. באמצעות createAndroidComposeRule, אפשר להפעיל בקלות את פעולת ממשק המשתמש שמסיימת את הפעילות, כמו שמוצג בקטע הקוד הבא:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()
@Test fun testResult() {
composeTestRule.onNodeWithTag("finish_button").performClick()
val scenario = composeTestRule.activityRule.scenario
val resultCode = scenario.result.resultCode
val resultData = scenario.result.resultData
}
}
הפעלת פעולות בפעילות
כל השיטות ב-ActivityScenario הן קריאות חוסמות, ולכן ה-API דורש להפעיל אותן בשרשור האינסטרומנטציה.
כדי להפעיל פעולות בפעילות שנבדקת, משתמשים בממשקי ה-API של בדיקות Compose כדי ליצור אינטראקציה עם רכיבי ה-Composable:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@get:Rule
val composeTestRule = createAndroidComposeRule<MyActivity>()
@Test fun testEvent() {
composeTestRule.onNodeWithText("Refresh").performClick()
}
}
עם זאת, אם אתם צריכים להפעיל method בפעילות עצמה, אתם יכולים לעשות זאת בבטחה באמצעות onActivity:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEvent() {
launchActivity<MyActivity>().use { scenario ->
scenario.onActivity { activity ->
activity.handleSwipeToRefresh()
}
}
}
}
מקורות מידע נוספים
מידע נוסף על בדיקות זמין במקורות המידע הבאים: