סנכרון הבדיקות

כברירת מחדל, בדיקות הפיתוח הנייטיב מסונכרנות עם ממשק המשתמש. כשקוראים לטענת נכוֹנוּת (assertion) או לפעולה באמצעות ComposeTestRule, הבדיקה מסונכרנת מראש וממתינה עד שעץ ממשק המשתמש בלי פעילות.

בדרך כלל, לא צריך לבצע שום פעולה. עם זאת, יש כמה מקרים מיוחדים שחשוב להכיר.

כשמבצעים סנכרון של בדיקה, השעון הווירטואלי מקדם את הזמן באפליקציית Compose. המשמעות היא שבדיקות של כתיבת קוד לא מופעלות בזמן אמת, ולכן הן יכולות לעבור כמה שיותר מהר.

עם זאת, אם לא תשתמשו בשיטות שמסנכרנות את הבדיקות, לא תתבצע קומפוזיציה מחדש והממשק ייראה כאילו הוא מושהה.

@Test
fun counterTest() {
    val myCounter = mutableStateOf(0) // State that can cause recompositions.
    var lastSeenValue = 0 // Used to track recompositions.
    composeTestRule.setContent {
        Text(myCounter.value.toString())
        lastSeenValue = myCounter.value
    }
    myCounter.value = 1 // The state changes, but there is no recomposition.

    // Fails because nothing triggered a recomposition.
    assertTrue(lastSeenValue == 1)

    // Passes because the assertion triggers recomposition.
    composeTestRule.onNodeWithText("1").assertExists()
}

הערה: הדרישה הזו חלה רק על היררכיות של Compose ולא על שאר האפליקציה.

השבתת הסנכרון האוטומטי

כשקוראים לטענת נכוֹנוּת (assertion) או לפעולה באמצעות ComposeTestRule כמו assertExists(), הבדיקה מסונכרנת עם ממשק המשתמש של פיתוח נייטיב. יכול להיות שבמקרים מסוימים תרצו להפסיק את הסנכרון הזה ולשלוט בשעון בעצמכם. לדוגמה, אתם יכולים לשלוט בזמן כדי לצלם צילומי מסך מדויקים של אנימציה בנקודה שבה ממשק המשתמש עדיין יהיה עסוק. כדי להשבית את הסנכרון האוטומטי, צריך להגדיר את המאפיין autoAdvance ב-mainClock לערך false:

composeTestRule.mainClock.autoAdvance = false

בדרך כלל, בשלב הזה אתם מקדמים את השעה בעצמכם. אפשר להתקדם בדיוק פריים אחד עם advanceTimeByFrame() או להתקדם למשך זמן ספציפי עם advanceTimeBy():

composeTestRule.mainClock.advanceTimeByFrame()
composeTestRule.mainClock.advanceTimeBy(milliseconds)

משאבים בלי פעילות

הכלי Compose יכול לסנכרן בין הבדיקות לבין ממשק המשתמש, כך שכל פעולה וכל טענת נכוֹנוּת (assertion) מתבצעות במצב בלי פעילות, תוך המתנה או קידום של השעון לפי הצורך. עם זאת, אפשר להריץ ברקע פעולות אסינכרוניות שהתוצאות שלהן משפיעות על מצב ממשק המשתמש, בלי שהבדיקה תהיה מודעת להן.

כדאי ליצור ולרשום את משאבי ההמתנה לפעילות האלה בבדיקה, כדי שהם ייכללו בהחלטה אם האפליקציה שנבדקת עסוקה או בלי פעילות. אין צורך לבצע פעולה כלשהי, אלא אם אתם צריכים לרשום משאבים נוספים של חוסר פעילות. לדוגמה, אם אתם מפעילים משימה ברקע שלא מסונכרנת עם Espresso או עם Compose.

ה-API הזה דומה מאוד ל-Idling Resources של Espresso, ומציין אם הנושא שנבדק נמצא במצב סרק או במצב פעיל. משתמשים בכלל הבדיקה Compose כדי לרשום את ההטמעה של IdlingResource.

composeTestRule.registerIdlingResource(idlingResource)
composeTestRule.unregisterIdlingResource(idlingResource)

סנכרון ידני

במקרים מסוימים, צריך לסנכרן את ממשק המשתמש של Compose עם חלקים אחרים של הבדיקה או של האפליקציה שנבדקת.

הפונקציה waitForIdle() מחכה שמצב הפעולה של פיתוח נייטיב יהיה 'בלי פעילות', אבל הפונקציה תלויה במאפיין autoAdvance:

composeTestRule.mainClock.autoAdvance = true // Default
composeTestRule.waitForIdle() // Advances the clock until Compose is idle.

composeTestRule.mainClock.autoAdvance = false
composeTestRule.waitForIdle() // Only waits for idling resources to become idle.

שימו לב שבשני המקרים, waitForIdle() גם מחכה למעברים של ציור ופריסה בהמתנה.

בנוסף, אפשר להריץ את השעון קדימה עד שתנאי מסוים מתקיים באמצעות advanceTimeUntil().

composeTestRule.mainClock.advanceTimeUntil(timeoutMs) { condition }

חשוב לשים לב שהתנאי שצוין צריך לבדוק את המצב שיכול להיות מושפע מהשעון הזה (הוא פועל רק עם מצב Compose).

המתנה לתנאים

כל תנאי שתלוי בעבודה חיצונית, כמו טעינת נתונים או מדידה או ציור של Android (כלומר, מדידה או ציור חיצוניים ל-Compose), צריך להשתמש במושג כללי יותר כמו waitUntil():

composeTestRule.waitUntil(timeoutMs) { condition }

אפשר גם להשתמש באחד מwaitUntilהעוזרים:

composeTestRule.waitUntilAtLeastOneExists(matcher, timeoutMs)

composeTestRule.waitUntilDoesNotExist(matcher, timeoutMs)

composeTestRule.waitUntilExactlyOneExists(matcher, timeoutMs)

composeTestRule.waitUntilNodeCount(matcher, count, timeoutMs)

מקורות מידע נוספים

  • בדיקת אפליקציות ב-Android: דף הנחיתה הראשי בנושא בדיקות ב-Android מספק סקירה רחבה יותר של עקרונות וטכניקות בדיקה.
  • היסודות של בדיקות: מידע נוסף על המושגים הבסיסיים שמאחורי בדיקת אפליקציית Android.
  • בדיקות מקומיות: אתם יכולים להריץ כמה בדיקות באופן מקומי, בתחנת העבודה שלכם.
  • בדיקות עם מכשור: מומלץ להריץ גם בדיקות עם מכשור. כלומר, בדיקות שמופעלות ישירות במכשיר.
  • אינטגרציה רציפה (CI): אינטגרציה רציפה מאפשרת לכם לשלב את הבדיקות בצינור הפריסה.
  • בדיקה של גדלי מסך שונים: יש למשתמשים הרבה מכשירים שונים, ולכן כדאי לבדוק גדלים שונים של מסכים.
  • Espresso: למרות שהכלי מיועד לממשקי משתמש מבוססי-View, הידע ב-Espresso יכול להיות שימושי גם לבדיקה של חלק מההיבטים ב-Compose.