בדיקה מקומית פועלת ישירות בתחנות העבודה שלכם, ולא ב-Android המכשיר או אמולטור. לכן, הוא משתמש במכונה הווירטואלית Java (JVM) המקומית שלכם במקום מכשיר Android כדי להריץ בדיקות. בדיקות מקומיות מאפשרות לכם להעריך את התוצאות את הלוגיקה של האפליקציה במהירות רבה יותר. אבל לא תהיה לנו אפשרות לקיים אינטראקציה עם מסגרת Android יוצרת הגבלה על סוגי הבדיקות שאפשר להריץ.
בדיקה של יחידה מאמתת את ההתנהגות של קטע קטן של קוד, היחידה בדיקה. הוא עושה זאת על ידי הרצת הקוד ובדיקת התוצאה.
בדיקות יחידה הן בדרך כלל פשוטות, אבל ההגדרה שלהן עלולה להיות בעייתית, כאשר 'בבדיקה' לא נועדה להביא בחשבון את יכולת הבדיקה:
- הקוד שרוצים לאמת צריך להיות נגיש בבדיקה. עבור לדוגמה, אי אפשר לבדוק שיטה פרטית באופן ישיר. במקום זאת, בודקים את הכיתה באמצעות ממשקי ה-API הציבוריים שלו.
- כדי להריץ בדיקות יחידה במצב בידוד, יחסי התלות של היחידה בבדיקות שנערכו, צריך להחליף אותם ברכיבים שנמצאים בשליטתכם, כמו מוצרים מזויפים מכפילים נוספים. הדבר בעייתי במיוחד אם הקוד שלך תלוי המסגרת של Android.
למידע על אסטרטגיות נפוצות לבדיקת יחידות ב-Android, קראו את המאמר מה צריך? בדיקה.
מיקום בדיקות מקומיות
כברירת מחדל, קובצי המקור עבור בדיקות של יחידה מקומית נמצאים
module-name/src/test/
הספרייה הזו כבר קיימת כשיוצרים תיקייה חדשה
בפרויקט באמצעות Android Studio.
הוספת יחסי תלות לבדיקה
צריך גם להגדיר את יחסי התלות לבדיקה עבור הפרויקט שלך כדי להשתמש ממשקי API סטנדרטיים שסופקו על ידי מסגרת הבדיקה של JUnit.
כדי לעשות זאת, צריך לפתוח את הקובץ build.gradle
של המודול של האפליקציה ולציין את הפרטים הבאים
של ספריות כיחסי תלות. צריך להשתמש בפונקציה testImplementation
כדי לציין
שהם חלים על קבוצת מקור הבדיקה המקומית, ולא על האפליקציה:
dependencies {
// Required -- JUnit 4 framework
testImplementation "junit:junit:$jUnitVersion"
// Optional -- Robolectric environment
testImplementation "androidx.test:core:$androidXTestVersion"
// Optional -- Mockito framework
testImplementation "org.mockito:mockito-core:$mockitoVersion"
// Optional -- mockito-kotlin
testImplementation "org.mockito.kotlin:mockito-kotlin:$mockitoKotlinVersion"
// Optional -- Mockk framework
testImplementation "io.mockk:mockk:$mockkVersion"
}
יצירת כיתה לבדיקת יחידה מקומית
אתם כותבים את הכיתה של בדיקת היחידה המקומית ככיתת מבחן של JUnit 4.
כדי לעשות זאת, צריך ליצור כיתה שמכילה שיטת בדיקה אחת או יותר, בדרך כלל
module-name/src/test/
שיטת בדיקה מתחילה עם ההערה @Test
ו-
מכיל את הקוד להפעלה ואימות של היבט יחיד של הרכיב
שאתם רוצים לבדוק.
הדוגמה הבאה ממחישה איך מטמיעים מחלקה של בדיקת יחידה מקומית.
שיטת בדיקה emailValidator_correctEmailSimple_returnsTrue()
מנסה לבצע אימות
isValidEmail()
,שהיא שיטה באפליקציה. פונקציית הבדיקה תחזיר
True אםisValidEmail()
גם מחזירה True.
Kotlin
import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test class EmailValidatorTest { @Test fun emailValidator_CorrectEmailSimple_ReturnsTrue() { assertTrue(EmailValidator.isValidEmail("name@email.com")) } }
Java
import org.junit.Test; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; class EmailValidatorTest { @Test public void emailValidator_CorrectEmailSimple_ReturnsTrue() { assertTrue(EmailValidator.isValidEmail("name@email.com")); } }
עליך ליצור בדיקות קריאות שמעריכות אם הרכיבים
האפליקציה תחזיר את התוצאות הצפויות. מומלץ להשתמש בספריית טענות נכונות (assertions),
בתור junit.Assert, Hamcrest, או
האמת. קטע הקוד שלמעלה הוא דוגמה לאופן השימוש
junit.Assert
ספריית Android שאפשר ליצור בה הדמיה
כשמבצעים בדיקות של יחידה מקומית, הפלאגין של Android Gradle כולל שמכילה את כל ממשקי ה-API של המסגרת של Android, שבה נעשה שימוש בפרויקט שלך. בספרייה נמצאים כל השיטות הציבוריות ה-methods של ממשקי ה-API האלה, אבל הקוד שבתוך השיטות הוסר. אם בכלל של השיטות שניגשים אליהן, הבדיקה גורמת לחריגה.
כך אפשר לבנות בדיקות מקומיות כשמפנות למחלקות ב-Android.
כמו Context
. וחשוב יותר, היא מאפשרת להשתמש
את ה-framework עם המחלקות של Android.
הדמיית יחסי תלות של Android
בעיה טיפוסית היא לגלות שכיתה משתמשת במשאב מחרוזות. אפשר
לקבל משאבי מחרוזות באמצעות קריאה ל-method getString()
ב-Context
בכיתה. עם זאת, בדיקה מקומית לא יכולה להשתמש ב-Context
או בכל אחת מהשיטות שלה כי
שייכים ל-framework של Android. במצב אידיאלי, השיחה אל getString()
תהיה
עברו מהכיתה, אבל לא תמיד זה מעשי. הפתרון הוא
יוצרים הדמיה או stub של Context
שתמיד מחזירים את אותו ערך
השיטה getString()
הופעלה.
באמצעות ספריית Android שניתן ליצור בה הדמיה ומסגרות לעג, כמו אפשר לתכנת את Mockito או MockK התנהגות החיקויים של מחלקות Android בבדיקות היחידה.
כדי להוסיף אובייקט מדומה לבדיקת היחידה המקומית באמצעות Mockito, מבצעים את הפעולות הבאות מודל תכנות:
- כוללים את התלות של ספריית Mockito בקובץ
build.gradle
, באופן הבא: שמתואר בהגדרת סביבת הבדיקה. - בתחילת ההגדרה של הכיתה בבדיקת היחידה, מוסיפים את הפקודה
הערה אחת (
@RunWith(MockitoJUnitRunner.class)
). הערה זו מראה מריץ בדיקה לדוגמה כדי לוודא שהשימוש שלך ב-framework נכון מפשט את האתחול של אובייקטים לדוגמה. - כדי ליצור אובייקט מדומה על תלות ב-Android, יש להוסיף את ההערה
@Mock
לפני הצהרת השדה. - כדי לפגוע בהתנהגות של התלות, אפשר לציין תנאי
של הערך המוחזר כשהתנאי מתקיים באמצעות הפונקציה
when()
ו-thenReturn()
שיטות.
הדוגמה הבאה ממחישה איך אפשר ליצור בדיקת יחידה שמבוססת על מודל
אובייקט Context
ב-Kotlin שנוצר באמצעות Mockito-Kotlin.
import android.content.Context
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
private const val FAKE_STRING = "HELLO WORLD"
@RunWith(MockitoJUnitRunner::class)
class MockedContextTest {
@Mock
private lateinit var mockContext: Context
@Test
fun readStringFromContext_LocalizedString() {
// Given a mocked Context injected into the object under test...
val mockContext = mock<Context> {
on { getString(R.string.name_label) } doReturn FAKE_STRING
}
val myObjectUnderTest = ClassUnderTest(mockContext)
// ...when the string is returned from the object under test...
val result: String = myObjectUnderTest.getName()
// ...then the result should be the expected one.
assertEquals(result, FAKE_STRING)
}
}
מידע נוסף על השימוש ב-Mockito framework זמין ב-Mockito API
והכיתה SharedPreferencesHelperTest
ב
קוד לדוגמה. כדאי לנסות גם את Android Testing Codelab.
שגיאה: "השיטה ... לא mocked"
אם מנסים לגשת לאחד מהדפדפנים, ספריית Android ניתנת להדמיה גורמת לחריגה מברירת המחדל.
שיטות עם ההודעה Error: "Method ... not mocked
.
אם החריגות שמזוהות בעייתיות בבדיקות שלך, אפשר לשנות את
כך ש-methods יחזירו null או אפס, בהתאם
. כדי לעשות זאת, צריך להוסיף את ההגדרות הבאות לחשבון של הפרויקט
קובץ build.gradle
ברמה העליונה ב-Groovy:
android {
...
testOptions {
unitTests.returnDefaultValues = true
}