כשבודקים רכיב או מערכת של רכיבים, עושים זאת בבידוד. לדוגמה, כדי לבדוק ViewModel, לא צריך להפעיל אמולטור ולהפעיל ממשק משתמש כי הוא לא תלוי (או לא אמור להיות תלוי) במסגרת Android.
עם זאת, יכול להיות שהנושא שנבדק תלוי בגורמים אחרים כדי לפעול. לדוגמה, יכול להיות ש-ViewModel תהיה תלויה במאגר נתונים כדי לפעול.
כשצריך לספק תלות לנושא הבדיקה, שיטה נפוצה היא ליצור אובייקט כפול לבדיקה (או אובייקט בדיקה). עותקים כפולים לבדיקה הם אובייקטים שנראים ומתנהגים כמו רכיבים באפליקציה, אבל הם נוצרים בבדיקה כדי לספק התנהגות או נתונים ספציפיים. היתרונות העיקריים הם שהם הופכים את הבדיקות מהירות ופשוטות יותר.
סוגי דמויי-בדיקה
יש כל מיני סוגים של מכפילים של בדיקה:
מזויף | עותק כפול לבדיקה עם הטמעה 'פועלת' של הכיתה, אבל היא מוטמעת בצורה שמתאימה לבדיקות אבל לא מתאימה לסביבת הייצור.
דוגמה: מסד נתונים בזיכרון. מוצרים מזויפים לא דורשים מסגרת לועגת, והם קלים. הן מומלצות. |
---|---|
הדמיה | ניסוי כפול מתנהג לפי האופן שבו אתם מתכנתים אותו, ושיש לו ציפיות לגבי האינטראקציות שלו. בדיקות של מודלים מדומים ייכשל אם האינטראקציות שלהם לא תואמות לדרישות שהגדרתם. כדי להשיג את כל זה, בדרך כלל יוצרים דוגמאות באמצעות מסגרת משעשעת.
דוגמה: אימות ששיטה במסד נתונים הוזמנה בדיוק פעם אחת. |
Stub | עותק בדיקה שמתנהג כפי שתכננתם אותו, אבל אין לו ציפיות לגבי האינטראקציות שלו. בדרך כלל נוצרים באמצעות מסגרת של בדיקת מודלים. עדיף להשתמש ב-Fakes במקום ב-stubs, מטעמי פשטות. |
dummy | ערך כפול של בדיקה שמועבר אבל לא בשימוש, למשל אם אתם צריכים רק לספק אותו כפרמטר.
דוגמה: פונקציה ריקה שהועברה כקריאה חוזרת (callback) של קליק. |
מרגל | wrapper מעל אובייקט אמיתי שעוקב גם אחרי מידע נוסף מסוים, בדומה לחיקויים. בדרך כלל, מומלץ להימנע מהם כדי לא להוסיף מורכבות. לכן, מומלץ להשתמש במודלים מזויפים או במודלים מדומים במקום במודלים של ריגול. |
צל | זיוף שנעשה בו שימוש ב-Robolectric. |
דוגמה לשימוש בזיוף
נניח שאתם רוצים לבצע בדיקת יחידה של ViewModel שמבוסס על ממשק שנקרא UserRepository
וחושף את שם המשתמש הראשון לממשק המשתמש. כדי ליצור בדיקת כפולה מזויפת, אפשר להטמיע את הממשק והחזרת הנתונים הידועים.
object FakeUserRepository : UserRepository {
fun getUsers() = listOf(UserAlice, UserBob)
}
val const UserAlice = User("Alice")
val const UserBob = User("Bob")
UserRepository
המזויף לא צריך להיות תלוי במקורות הנתונים המקומיים והמרוחקים שבהם גרסת הייצור תשתמש. הקובץ נמצא בקבוצת מקורות הבדיקה ולא יישלח עם אפליקציית הייצור.

הבדיקה הבאה מוודאת ש-ViewModel חושף בצורה נכונה את שם המשתמש הראשון לתצוגה.
@Test
fun viewModelA_loadsUsers_showsFirstUser() {
// Given a VM using fake data
val viewModel = ViewModelA(FakeUserRepository) // Kicks off data load on init
// Verify that the exposed data is correct
assertEquals(viewModel.firstUserName, UserAlice.name)
}
בבדיקת יחידה אפשר להחליף בקלות את UserRepository
בזיוף, כי ה-ViewModel נוצר על ידי הבודק. עם זאת, יכול להיות מאתגר להחליף רכיבים שרירותיים בבדיקות גדולות יותר.
החלפת רכיבים והחדרת תלות
כשאין לבדיקות שליטה על יצירת המערכות שנבדקות, החלפת רכיבים ברכיבי בדיקה כפולים הופכת למורכבת יותר, ודורשת שהארכיטקטורה של האפליקציה תעמוד בדרישות של עיצוב ניתן לבדיקה.
גם בדיקות גדולות מקצה לקצה יכולות להפיק תועלת מהשימוש במכפילים של בדיקה, כמו בדיקה אינסטרומנטלית של ממשק משתמש שמנווטת בתהליך מלא של המשתמש באפליקציה. במקרה כזה, כדאי שהבדיקה תהיה הרמטית. בדיקה הרמטית מונעת יחסי תלות חיצוניים, כמו אחזור נתונים מהאינטרנט. כך אפשר לשפר את האמינות והביצועים.

אפשר לעצב את האפליקציה כך שתשיג את הגמישות הזו באופן ידני, אבל מומלץ להשתמש ב-framework של החדרת תלות כמו Hilt כדי להחליף רכיבים באפליקציה בזמן הבדיקה. מדריך הבדיקה של Hilt
השלבים הבאים
בדף שיטות בדיקה מוסבר איך אפשר לשפר את הפרודוקטיביות באמצעות סוגים שונים של בדיקות.