בדיקה מול שינויים בהגדרות המסך באמצעות Espresso Device API

אפשר להשתמש ב-Espresso Device API כדי לבדוק את האפליקציה כשמתבצעים במכשיר שינויים נפוצים בהגדרות, כמו סיבוב ופתיחת המסך. ‫Espresso Device API הוא הכלי המומלץ לביצוע פעולות ברמת המכשיר לצד כללי הבדיקה של Jetpack Compose. אם אתם חדשים בכתיבת בדיקות ממשק משתמש ל-Jetpack Compose, כדאי לעיין במאמר בדיקת פריסת Compose.

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

כדי להשתמש ב-Espresso Device API, אתם צריכים:

  • ‫Android Studio Iguana או גרסה מתקדמת יותר
  • פלאגין של Android Gradle גרסה 8.3 ואילך
  • אמולטור Android מגרסה 33.1.10 ואילך
  • מכשיר וירטואלי של Android עם רמת API 24 ומעלה

הגדרת הפרויקט ל-Espresso Device API

כדי להגדיר את הפרויקט כך שיתמוך ב-Espresso Device API, מבצעים את הפעולות הבאות:

  1. כדי לאפשר לבדיקה להעביר פקודות למכשיר הבדיקה, מוסיפים את הרשאות הרשת הנדרשות לקובץ המניפסט בערכת המקור androidTest:

      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    

    אם הבדיקה מטרגטת Android 17 (רמת API 37) ומעלה, צריך גם להצהיר על ההרשאה ACCESS_LOCAL_NETWORK:

      <uses-permission android:name="android.permission.ACCESS_LOCAL_NETWORK" />
    
  2. מפעילים את הדגל הניסיוני enableEmulatorControl בקובץ gradle.properties:

      android.experimental.androidTest.enableEmulatorControl=true
    
  3. מפעילים את האפשרות emulatorControl בסקריפט הבנייה ברמת המודול:

    Kotlin

      testOptions {
        emulatorControl {
          enable = true
        }
      }
      

    מגניב

      testOptions {
        emulatorControl {
          enable = true
        }
      }
      
  4. בסקריפט הבנייה ברמת המודול, מייבאים את ספריית Espresso Device לפרויקט:

    Kotlin

    dependencies {
      androidTestImplementation("androidx.test.espresso:espresso-device:1.1.0")
    }

    מגניב

    dependencies {
      androidTestImplementation 'androidx.test.espresso:espresso-device:1.1.0'
    }

בדיקה של שינויים נפוצים בהגדרות

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

בדיקה מול סיבוב המסך

כדי לבדוק את סיבוב המסך, אפשר להשתמש במחלקה ScreenOrientationRule כדי להגדיר את כיוון המכשיר במהלך הבדיקה.

דוגמה לבדיקה של מה שקורה לאפליקציה כשמסובבים את המסך של המכשיר:

  1. קודם צריך להגדיר את כלל הבדיקה של Compose ולהשתמש במחלקה ScreenOrientationRule כדי להגדיר את המכשיר למצב התחלתי עקבי (למשל, מצב אנכי):

    import androidx.compose.ui.test.assertIsDisplayed
    import androidx.compose.ui.test.assertDoesNotExist
    import androidx.compose.ui.test.junit4.createComposeRule
    import androidx.compose.ui.test.onNodeWithTag
    import androidx.test.espresso.device.EspressoDevice.onDevice
    import androidx.test.espresso.device.action.ScreenOrientation
    import androidx.test.espresso.device.rules.ScreenOrientationRule
    import org.junit.Rule
    import org.junit.Test
    
    class MyConfigurationTest {
    
        // 1. Define the Compose test rule
        @get:Rule
        val composeTestRule = createComposeRule()
    
        // 2. Define the Espresso Device rule for a consistent starting state
        @get:Rule
        val screenOrientationRule = ScreenOrientationRule(ScreenOrientation.PORTRAIT)
    }
    

    אם הבדיקה מטרגטת ל-Android 17 (רמת API 37) ומעלה, נדרשת הרשאת ACCESS_LOCAL_NETWORK ל-Espresso Device API. צריך לוודא שההרשאה הזו ניתנה לפני שמפעילים את הכלל ScreenOrientationRule. משתמשים ב-RuleChain של JUnit כדי להפעיל קודם את הכלל GrantPermissionRule:

    import androidx.test.rule.GrantPermissionRule
    import org.junit.rules.RuleChain
    
    class MyConfigurationTest {
        val grantPermissionRule = GrantPermissionRule.grant(android.Manifest.permission.ACCESS_LOCAL_NETWORK)
        val composeTestRule = createComposeRule()
        val screenOrientationRule = ScreenOrientationRule(ScreenOrientation.PORTRAIT)
    
        @get:Rule
        val chain = RuleChain
            .outerRule(grantPermissionRule)
            .around(composeTestRule)
            .around(screenOrientationRule)
    }
    
  2. יוצרים בדיקה שמגדירה את המכשיר לתצוגה לרוחב במהלך ביצוע הבדיקה:

    @Test
    fun myRotationTest() {
      ...
      // Sets the device to landscape orientation during test execution.
      onDevice().setScreenOrientation(ScreenOrientation.LANDSCAPE)
      ...
    }
    
  3. אחרי שהמסך מסתובב, משתמשים ב-composeTestRule כדי לוודא שרכיבי ה-Composable מותאמים למצב החדש כמו שציפיתם.

    @Test
    fun myRotationTest() {
      ...
      // Sets the device to landscape orientation during test execution.
      onDevice().setScreenOrientation(ScreenOrientation.LANDSCAPE)
      composeTestRule.onNodeWithTag("NavRail").assertIsDisplayed()
      composeTestRule.onNodeWithTag("BottomBar").assertDoesNotExist()
    }
    

בדיקה מול פתיחת המסך

הנה דוגמה לאופן שבו ניתן לבדוק מה קורה לאפליקציה שלך אם היא מותקנת במכשיר מתקפל והמסך נפתח:

  1. קודם, צריך לבדוק את המכשיר כשהוא מקופל על ידי התקשרות אל onDevice().setClosedMode(). חשוב לוודא שהקומפוזיציות מותאמות לרוחב המסך הקומפקטי.

    @Test
    fun myUnfoldedTest() {
      onDevice().setClosedMode()
      composeTestRule.onNodeWithTag("BottomBar").assertIsDisplayed()
      composeTestRule.onNodeWithTag("NavRail").assertDoesNotExist()
      ...
    }
    
  2. כדי לעבור למצב פתוח לגמרי, מתקשרים אל onDevice().setFlatMode(). בודקים שהקומפוזיציות מותאמות לסיווג הגודל המורחב.

    @Test
    fun myUnfoldedTest() {
      onDevice().setClosedMode()
      ...
      onDevice().setFlatMode()
      composeTestRule.onNodeWithTag("NavRail").assertIsDisplayed()
      composeTestRule.onNodeWithTag("BottomBar").assertDoesNotExist()
    }
    

ציון המכשירים שנדרשים לבדיקות

אם מריצים בדיקה שמבצעת פעולות קיפול במכשיר שלא ניתן לקיפול, סביר להניח שהבדיקה תיכשל. כדי להריץ רק את הבדיקות שרלוונטיות למכשיר הפועל, משתמשים בהערה @RequiresDeviceMode. כלי ההרצה של הבדיקות מדלג באופן אוטומטי על הרצת בדיקות במכשירים שלא תומכים בהגדרה שנבדקת. אפשר להוסיף את כלל הדרישה למכשיר לכל בדיקה או לכל מחלקת בדיקה.

לדוגמה, כדי לציין שבדיקה צריכה לפעול רק במכשירים שתומכים בפתיחה לתצורה שטוחה, מוסיפים את הקוד @RequiresDeviceMode הבא לבדיקה:

@Test
@RequiresDeviceMode(mode = FLAT)
fun myUnfoldedTest() {
  ...
}