Spectatio: מסגרת בדיקה לרכב

Spectatio היא מסגרת בדיקה בקוד פתוח שפותחה לבדיקה של Android Automotive OS‏ (AAOS) במכשירים אמיתיים וווירטואליים. חברת Spectatio מספקת ממשקי API לבדיקת אפליקציות במכשירי רכב, והפתרון הזה ניתן להרחבה ולהתאמה, שמשמש לאימות היכולת והביצועים של AAOS ושל האפליקציות שלו.

העיצוב הכללי

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

האיור הבא מסביר את העיצוב הכללי של מסגרת Spectatio.

העיצוב הכללי של מסגרת Spectatio

איור 1. עיצוב ברמה גבוהה של Spectatio framework.

מסגרת Spectatio מבוססת על UI Automator, ומספקת קבוצה של ממשקי API ליצירת בדיקות ממשק משתמש שמקיימות אינטראקציה עם אפליקציות של משתמשים ושל מערכות ב-AAOS. בבדיקות לכלי רכב נעשה שימוש בממשקי ה-API שסופקו על ידי מסגרת Spectatio לצורך בדיקה. כך הבדיקות האלה עצמאיות מהמכשיר שנבדק (DUT) וניתן להתאים אותן לבדיקה של מכשירים שונים, אם הם נתמכים.

באיור 1 אפשר לראות ש-Spectatio הוא מסגרת מודולרית שמבוססת על אפליקציות עזר כמו Dialer‏, Medicenter והגדרות, באמצעות ממשקים ורכיבי עזר ספציפיים לאפליקציות. כך אפשר להרחיב אותו בקלות לאפליקציות חדשות. המסגרת של Spectatio משתמשת שוב בסטנדרטים הנפוצים ובכיתות העזר של התשתית. כיתת העזר הרגילה היא הכיתה ההורה של כל פונקציות העזר של האפליקציה, והיא מספקת פונקציות רגילות ספציפיות למכשיר או פונקציות שחלות על אפליקציות שונות. כיתות העזר של השירותים מספקות שירותים כמו קריאה או כתיבת קבצים מהמכשיר.

ארכיטקטורה

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

באיור 2 מוצגת הארכיטקטורה ברמה גבוהה של מסגרת Spectatio וכל הישויות שמעורבות בהטמעת ממשקי API לבדיקה של אפליקציה.

ארכיטקטורה ברמה גבוהה של מסגרת Spectatio

איור 2. הארכיטקטורה ברמה גבוהה של מסגרת Spectatio.

ממשק ה-App Helper מספק תוכנית להטמעה של App Helper. הוא מורכב מפונקציות עזר שונות שנדרשות לבדיקת אפליקציות. לכל אפליקציה יש ממשק משלה, כמו IAutoSettingHelper ו-IAutoDialHelper. מידע נוסף ורשימת פונקציות ממשק זמינים במאמר פונקציות ממשק של כלי עזר לאפליקציות ב-AOSP.

סיווג העזרה הרגיל מורכב ממאפיינים ופונקציות רגילים שנדרשים להגדרת המכשיר, אבל הם לא ספציפיים לאף אפליקציה, כמו pressHome ו-scroll. סיווג העזרה הרגיל מוגדר ב-AbstractAutoStandardAppHelper.java.

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

מודול הטמעת העזרה לאפליקציה הוא הליבה של מסגרת Spectatio. היא כוללת את ההטמעה של פונקציות העזרה שמוגדרות בממשק העזרה של האפליקציות, שנדרשות לבדיקת אפליקציות במכשיר רכב. לכל אפליקציה יש הטמעה משלה, כמו SettingHelperImpl ו-DialHelperImpl, שבהן נעשה שימוש בבדיקות הרכב לצורך בדיקת האפליקציות. למידע נוסף ורשימת הטמעות, ראו פונקציות להטמעת כלי עזר לאפליקציות ב-AOSP.

בבדיקות לכלי רכב נעשה שימוש בפונקציות ההטמעה של ה-App Helper כדי לבדוק פעולות שונות שקשורות לאפליקציה. כדי לקבל גישה לפונקציות ההטמעה של ה-App Helper, משתמשים בכיתה HelperAccessor.

הקוד הבא מציג את ההגדרה, הניקוי וההפעלה של בדיקת רכב לדוגמה.

@RunWith(AndroidJUnit4.class)
public class AutoApplicationTest {
  static HelperAccessor<IAutoApplicationHelper> autoApplicationHelper =
          new HelperAccessor<>(IAutoApplicationHelper.class);

  public AutoApplicationTest() {
    // constructor
    // Initialize any attributes that are required for the test execution
  }

  @Before
  public void beforeTest() {
    // Initial setup before each test
    // For example - open the app
    autoApplicationHelper.open();
  }

  @After
  public void afterTest() {
    // Cleanup after each test.
    // For example - exit the app
    autoApplicationHelper.exit();
  }

  @Test
  public void testApplicationFeature() {
    // Test
    // For example - Test if app is open
    assertTrue("Application is not open.", autoApplicationHelper.isOpen());
  }
}

התאמה אישית

ה-framework של Spectatio לא תלוי בממשק המשתמש של המכשיר, ולכן ניתן להתאים אותו לבדיקת מכשירים עם מגוון ממשקי משתמש וחומרה. כדי להשיג את יכולת ההתאמה הזו, Spectatio משתמש בתצורות ברירת המחדל של המכשיר בהתאם למכשיר העזר. כדי לתמוך בהגדרות מכשיר שאינן ברירת המחדל, המסגרת משתמשת בקובץ תצורה של JSON בזמן הריצה כדי להגדיר את השינויים הרצויים בממשק המשתמש של המכשיר. קובץ תצורה בפורמט JSON תומך ברכיבי ממשק משתמש כמו TEXT, ‏ DESCRIPTION ו-RESOURCE_ID, יחד עם הגדרות path, והוא חייב להכיל רק את המידע על השינויים בממשק המשתמש של ה-DUT. שאר רכיבי ממשק המשתמש משתמשים בערכי ברירת המחדל של ההגדרות שסופקו במסגרת.

הגדרות ברירת המחדל של המכשיר

בדוגמה הבאה של קובץ תצורה של JSON מוצגות ההגדרות הזמינות של המכשיר וערכי ברירת המחדל שלהן.

לחצו כאן כדי להציג קובץ תצורה לדוגמה בפורמט JSON

    {
        "SETTINGS": {
                "APPLICATION_CONFIG": {
                        "SETTINGS_TITLE_TEXT": "Settings",
                        "SETTINGS_PACKAGE": "com.android.car.settings",
                        "SETTINGS_RRO_PACKAGE": "com.android.car.settings.googlecarui.rro",
                        "OPEN_SETTINGS_COMMAND": "am start -a android.settings.SETTINGS",
                        "OPEN_QUICK_SETTINGS_COMMAND": "am start -n com.android.car.settings/com.android.car.settings.common.CarSettingActivity"
                },
                "QUICK_SETTINGS": {
                        "OPEN_MORE_SETTINGS": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "toolbar_menu_item_1",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "NIGHT_MODE": {
                                "TYPE": "TEXT",
                                "VALUE": "Night mode"
                        }
                },
                "DISPLAY": {
                        "PATH": "Settings > Display",
                        "OPTIONS": [
                                "Brightness level"
                        ],
                        "BRIGHTNESS_LEVEL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "seekbar",
                                "PACKAGE": "com.android.car.settings"
                        }
                },
                "SOUND": {
                        "PATH": "Settings > Sound",
                        "OPTIONS": [
                                "Media volume",
                                "Alarm volume"
                        ]
                },
                "NETWORK_AND_INTERNET": {
                        "PATH": "Settings > Network & internet",
                        "OPTIONS": [
                        ],
                        "TOGGLE_WIFI": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "master_switch",
                                "PACKAGE": "com.android.car.settings"
                        }
                },
                "BLUETOOTH": {
                        "PATH": "Settings > Bluetooth",
                        "OPTIONS": [
                        ],
                        "TOGGLE_BLUETOOTH": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_menu_item_switch",
                                "PACKAGE": "com.android.car.settings"
                        }
                },
                "APPS_AND_NOTIFICATIONS": {
                        "PATH": "Settings > Apps & notifications",
                        "OPTIONS": [
                        ],
                        "SHOW_ALL_APPS": {
                                "TYPE": "TEXT",
                                "VALUE": "Show all apps"
                        },
                        "ENABLE_DISABLE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_menu_item_text",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "DISABLE_BUTTON_TEXT": {
                                "TYPE": "TEXT",
                                "VALUE": "Disable"
                        },
                        "ENABLE_BUTTON_TEXT": {
                                "TYPE": "TEXT",
                                "VALUE": "Enable"
                        },
                        "DISABLE_APP_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "DISABLE APP"
                        },
                        "FORCE_STOP_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Force stop"
                        },
                        "OK_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "OK"
                        },
                        "PERMISSIONS_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Permissions"
                        },
                        "ALLOW_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Allow"
                        },
                        "DENY_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Deny"
                        },
                        "DENY_ANYWAY_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Deny anyway"
                        }
                },
                "DATE_AND_TIME": {
                        "PATH": "Settings > Date & time",
                        "OPTIONS": [
                                "Automatic date & time",
                "Automatic time zone"
                        ],
                        "AUTOMATIC_DATE_AND_TIME": {
                                "TYPE": "TEXT",
                                "VALUE": "Automatic date & time"
                        },
                        "AUTOMATIC_TIME_ZONE": {
                                "TYPE": "TEXT",
                                "VALUE": "Automatic time zone"
                        },
                        "SET_DATE": {
                                "TYPE": "TEXT",
                                "VALUE": "Set date"
                        },
                        "SET_TIME": {
                                "TYPE": "TEXT",
                                "VALUE": "Set time"
                        },
                        "SELECT_TIME_ZONE": {
                                "TYPE": "TEXT",
                                "VALUE": "Select time zone"
                        },
                        "USE_24_HOUR_FORMAT": {
                                "TYPE": "TEXT",
                                "VALUE": "Use 24-hour format"
                        },
                        "OK_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "toolbar_menu_item_0",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "NUMBER_PICKER_WIDGET": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.NumberPicker"
                        },
                        "EDIT_TEXT_WIDGET": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        }
                },
                "USERS": {
                        "PATH": "Settings > Users",
                        "OPTIONS": [
                                "Guest"
                        ]
                },
                "ACCOUNTS": {
                        "PATH": "Settings > Accounts",
                        "OPTIONS": [
                                "Automatically sync data"
                        ],
                        "ADD_ACCOUNT": {
                                "TYPE": "TEXT",
                                "VALUE": "ADD ACCOUNT"
                        },
                        "ADD_GOOGLE_ACCOUNT": {
                                "TYPE": "TEXT",
                                "VALUE": "Google"
                        },
                        "SIGN_IN_ON_CAR_SCREEN": {
                                "TYPE": "TEXT",
                                "VALUE": "Sign in on car screen"
                        },
                        "GOOGLE_SIGN_IN_SCREEN": {
                                "TYPE": "TEXT",
                                "VALUE": "Sign in to your Google Account"
                        },
                        "ENTER_EMAIL": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        },
                        "ENTER_PASSWORD": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        },
                        "NEXT_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Next"
                        },
                        "DONE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Done"
                        },
                        "REMOVE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Remove"
                        },
                        "REMOVE_ACCOUNT_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Remove Account"
                        }
                },
                "SYSTEM": {
                        "PATH": "Settings > System",
                        "OPTIONS": [
                                "About", "Legal information"
                        ],
                        "ABOUT_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "About"
                        },
                        "RESET_OPTIONS_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Reset options"
                        },
                        "LANGUAGES_AND_INPUT_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Languages & input"
                        },
                        "DEVICE_MODEL": {
                                "TYPE": "TEXT",
                                "VALUE": "Model"
                        },
                        "ANDROID_VERSION": {
                                "TYPE": "TEXT",
                                "VALUE": "Android version"
                        },
                        "ANDROID_SECURITY_PATCH_LEVEL": {
                                "TYPE": "TEXT",
                                "VALUE": "Android security patch level"
                        },
                        "KERNEL_VERSION": {
                                "TYPE": "TEXT",
                                "VALUE": "Kernel version"
                        },
                        "BUILD_NUMBER": {
                                "TYPE": "TEXT",
                                "VALUE": "Build number"
                        },
                        "RECYCLER_VIEW_WIDGET": {
                                "TYPE": "CLASS",
                                "VALUE": "androidx.recyclerview.widget.RecyclerView"
                        },
                        "RESET_NETWORK": {
                                "TYPE": "TEXT",
                                "VALUE": "Reset network"
                        },
                        "RESET_SETTINGS": {
                                "TYPE": "TEXT",
                                "VALUE": "RESET SETTINGS"
                        },
                        "RESET_APP_PREFERENCES": {
                                "TYPE": "TEXT",
                                "VALUE": "Reset app preferences"
                        },
                        "RESET_APPS": {
                                "TYPE": "TEXT",
                                "VALUE": "RESET APPS"
                        },
                        "LANGUAGES_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Languages"
                        },
                        "LANGUAGES_MENU_IN_SELECTED_LANGUAGE": {
                                "TYPE": "TEXT",
                                "VALUE": "Idiomas"
                        }
                },
                "SECURITY": {
                        "PATH": "Settings > Security",
                        "OPTIONS": [
                        ],
                        "TITLE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_title",
                                "PACKAGE": "com.android.car.settings.googlecarui.rro"
                        },
                        "CHOOSE_LOCK_TYPE": {
                                "TYPE": "TEXT",
                                "VALUE": "Choose a lock type"
                        },
                        "LOCK_TYPE_PASSWORD": {
                                "TYPE": "TEXT",
                                "VALUE": "Password"
                        },
                        "LOCK_TYPE_PIN": {
                                "TYPE": "TEXT",
                                "VALUE": "PIN"
                        },
                        "LOCK_TYPE_NONE": {
                                "TYPE": "TEXT",
                                "VALUE": "None"
                        },
                        "CONTINUE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Continue"
                        },
                        "CONFIRM_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Confirm"
                        },
                        "ENTER_PASSWORD": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        },
                        "PIN_PAD": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "pin_pad",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "ENTER_PIN_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "key_enter",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "REMOVE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Remove"
                        }
                }
        },
        "PHONE": {
                "APPLICATION_CONFIG": {
                        "DIAL_PACKAGE": "com.android.car.dialer",
                        "PHONE_ACTIVITY": "com.android.car.dialer/.ui.TelecomActivity",
                        "OPEN_DIAL_PAD_COMMAND": "am start -a android.intent.action.DIAL"
                },
                "IN_CALL_VIEW": {
                        "DIALED_CONTACT_TITLE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "user_profile_title",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "DIALED_CONTACT_NUMBER": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "user_profile_phone_number",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "END_CALL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "end_call_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "MUTE_CALL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "mute_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "SWITCH_TO_DIAL_PAD": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "toggle_dialpad_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CHANGE_VOICE_CHANNEL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "voice_channel_view",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "VOICE_CHANNEL_CAR": {
                                "TYPE": "TEXT",
                                "VALUE": "Car speakers"
                        },
                        "VOICE_CHANNEL_PHONE": {
                                "TYPE": "TEXT",
                                "VALUE": "Phone"
                        }
                },
                "DIAL_PAD_VIEW": {
                        "DIAL_PAD_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Dial Pad"
                        },
                        "DIAL_PAD_FRAGMENT": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "dialpad_fragment",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "DIALED_NUMBER": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "MAKE_CALL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "call_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "DELETE_NUMBER": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "delete_button",
                                "PACKAGE": "com.android.car.dialer"
                        }
                },
                "CONTACTS_VIEW": {
                        "CONTACTS_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Contacts"
                        },
                        "CONTACT_INFO": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "call_action_id",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_DETAIL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "show_contact_detail_id",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "ADD_CONTACT_TO_FAVORITE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "contact_details_favorite_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "SEARCH_CONTACT": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "menu_item_search",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_SEARCH_BAR": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_search_bar",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "SEARCH_RESULT": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "contact_name",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_SETTINGS": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "menu_item_setting",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_ORDER": {
                                "TYPE": "TEXT",
                                "VALUE": "Contact order"
                        },
                        "SORT_BY_FIRST_NAME": {
                                "TYPE": "TEXT",
                                "VALUE": "First name"
                        },
                        "SORT_BY_LAST_NAME": {
                                "TYPE": "TEXT",
                                "VALUE": "Last Name"
                        },
                        "CONTACT_TYPE_WORK": {
                                "TYPE": "TEXT",
                                "VALUE": "Work"
                        },
                        "CONTACT_TYPE_MOBILE": {
                                "TYPE": "TEXT",
                                "VALUE": "Mobile"
                        },
                        "CONTACT_TYPE_HOME": {
                                "TYPE": "TEXT",
                                "VALUE": "Home"
                        }
                },
                "CALL_HISTORY_VIEW": {
                        "CALL_HISTORY_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Recents"
                        },
                        "CALL_HISTORY_INFO": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "call_action_id",
                                "PACKAGE": "com.android.car.dialer"
                        }
                },
                "FAVORITES_VIEW": {
                        "FAVORITES_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Favorites"
                        }
                }
        },
        "NOTIFICATIONS": {
                "APPLICATION_CONFIG": {
                        "OPEN_NOTIFICATIONS_COMMAND": "service call statusbar 1"
                },
                "EXPANDED_NOTIFICATIONS_SCREEN": {
                        "NOTIFICATION_VIEW": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "notification_view",
                                "PACKAGE": "com.android.systemui"
                        },
                        "CLEAR_ALL_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "clear_all_button",
                                "PACKAGE": "com.android.systemui"
                        },
                        "STATUS_BAR": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_top_navigation_bar_container",
                                "PACKAGE": "com.android.systemui"
                        },
                        "APP_ICON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "app_icon",
                                "PACKAGE": "com.android.systemui"
                        },
                        "APP_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "header_text",
                                "PACKAGE": "com.android.systemui"
                        },
                        "NOTIFICATION_TITLE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "notification_body_title",
                                "PACKAGE": "com.android.systemui"
                        },
                        "NOTIFICATION_BODY": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "notification_body_content",
                                "PACKAGE": "com.android.systemui"
                        },
                        "CARD_VIEW": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "card_view",
                                "PACKAGE": "com.android.systemui"
                        }
                }
        },
        "MEDIA_CENTER": {
                "APPLICATION_CONFIG": {
                        "MEDIA_CENTER_PACKAGE": "com.android.car.media",
                        "MEDIA_ACTIVITY": "com.android.bluetooth/com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService"
                },
                "MEDIA_CENTER_SCREEN": {
                        "PLAY_PAUSE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "play_pause_stop",
                                "PACKAGE": "com.android.car.media"
                        },
                        "NEXT_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_next",
                                "PACKAGE": "com.android.car.media"
                        },
                        "PREVIOUS_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_prev",
                                "PACKAGE": "com.android.car.media"
                        },
                        "SHUFFLE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "overflow_on",
                                "PACKAGE": "com.android.car.media"
                        },
                        "PLAY_QUEUE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "play_queue",
                                "PACKAGE": "com.android.car.media"
                        },
                        "MINIMIZED_MEDIA_CONTROLS": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "minimized_playback_controls",
                                "PACKAGE": "com.android.car.media"
                        },
                        "TRACK_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.media"
                        },
                        "TRACK_NAME_MINIMIZED_CONTROL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "minimized_control_bar_title",
                                "PACKAGE": "com.android.car.media"
                        },
                        "BACK_BUTTON": {
                                "TYPE": "DESCRIPTION",
                                "VALUE": "Back"
                        }
                },
                "MEDIA_CENTER_ON_HOME_SCREEN": {
                        "PLAY_PAUSE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "play_pause_stop",
                                "PACKAGE": "com.android.car.carlauncher"
                        },
                        "NEXT_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_next",
                                "PACKAGE": "com.android.car.carlauncher"
                        },
                        "PREVIOUS_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_prev",
                                "PACKAGE": "com.android.car.carlauncher"
                        },
                        "TRACK_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.carlauncher"
                        }
                }
        }
}
  

הגדרות חלופיות של המכשיר

דוגמת הקוד הבאה מציגה דוגמה לקובץ תצורה של JSON שבו ההגדרות ב-DUT מבטלות את הגדרות ברירת המחדל. בדוגמה הזו:

  • ההגדרות של האינטרנט נקראות רשת ואינטרנט במכשירי העזר וקישוריות ב-DUT.

  • הגדרות התאריך והשעה זמינות בקטע הגדרות > תאריך ושעה במכשירי העזרה, ובקטע הגדרות > מערכת > תאריך ושעה ב-DUT.

// Default configuration file
{
    ....
    "SECURITY_SETTINGS_SCROLL_ELEMENT": {
      "TYPE": "RESOURCE_ID",
      "VALUE": "fragment_container",
    },
    ....
}

// JSON configuration file for non-reference device
{
    ....
    "SECURITY_SETTINGS_SCROLL_ELEMENT": {
      "TYPE": "RESOURCE_ID",
      "VALUE": "car_ui_recycler_view"
    },
    ....
}

כשקובץ התצורה בפורמט JSON מוכן, הוא מסופק במהלך זמן הריצה, כפי שמוצג בבלוק הקוד הבא:

# Push The JSON configuration file to the device
adb -s DEVICE-SERIAL push PATH-OF-JSON-FILE /data/local/tmp/runtimeSpectatioConfig.json

בפקודה הזו:

  • DEVICE-SERIAL: המזהה הסידורי של ה-DUT. הפרמטר הזה לא נדרש אם רק מכשיר אחד מחובר למארח.

  • PATH-TO-JSON-FILE: הנתיב של קובץ ה-JSON במכונה המארחת.

פורמט ההגדרות האישיות

בהגדרה יש חמישה אובייקטים ברמה העליונה, עם המפתחות והערכים הבאים:

אובייקט תיאור
PACKAGES אובייקט שמתאר את החבילה הראשית של אפליקציות שונות, שמשמשות לקביעת המצב שבו האפליקציה הזו נמצאת בחזית.
ACTIONS אובייקט שמציין סוגי פעולות ופרמטרים של פעולות שונות. לדוגמה, אם להשתמש בלחצנים או בתנועה כדי לגלול.
COMMANDS אובייקט שמציין פקודות שמבצעות פעולות שונות.
UI_ELEMENTS אובייקט שמשמש ליצירת 'BySelectors' של UI Automator שבוחרים רכיבי UI (מתוארים בפירוט בהמשך).
WORKFLOWS רצפי פעולות שמבצעים משימות ברמה גבוהה (מתוארים בפירוט בהמשך).

רכיבים בממשק המשתמש

לכל רכיב בממשק המשתמש יש TYPE שמציין את מה ש-UI Automator יחפש כדי לזהות את הרכיב (למשל, מזהה המשאב, הטקסט והתיאור) ואת ערכי התצורה שמשויכים לסוג הזה. באופן כללי, בכל פעם שרכיב עזר מזהה אלמנט במסך באמצעות ההגדרה הזו, הוא מקבל בדיוק אלמנט אחד. אם יש כמה רכיבים שתואמים להגדרה, המערכת תשתמש באחד מהם באופן שרירותי. לכן, ההגדרה צריכה (בדרך כלל) להיות ספציפית מספיק כדי לצמצם אותה לרכיב אחד בהקשר הרלוונטי.

טקסט

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

    "CALL_HISTORY_MENU": {
      "TYPE": "TEXT",
      "VALUE": "Recents"
    }

TEXT_CONTAINS

זהה ל-TEXT, מלבד העובדה ש-VALUE שצוין צריך להופיע רק במקום כלשהו בטקסט של הרכיב שרוצים להתאים.

    "PRIVACY_CALENDAR": {
      "TYPE": "TEXT_CONTAINS",
      "VALUE": "Calendar"
    }

תיאור

זיהוי האלמנט לפי מאפיין תיאור התוכן שלו, תוך דרישה להתאמה מדויקת.

    "APP_GRID_SCROLL_BACKWARD_BUTTON": {
      "TYPE": "DESCRIPTION",
      "VALUE": "Scroll up"
    }

RESOURCE_ID

מזהים את האלמנט לפי מזהה המשאב שלו, ואפשר גם לבדוק את רכיב החבילה של המזהה הזה. המפתח PACKAGE הוא אופציונלי. אם לא יושמטו, כל חבילה תתאים רק לחלק מהמזהה שמופיע אחרי :id/.

    "APP_LIST_SCROLL_ELEMENT": {
      "TYPE": "RESOURCE_ID",
      "VALUE": "apps_grid",
      "PACKAGE": "com.android.car.carlauncher"
    }

ניתנים ללחיצה ולגלילה

מזהים את האלמנט על סמך האפשרות ללחוץ עליו (או לא) או לגלול בו. אלה סוגים רחבים מאוד של רכיבים, ובדרך כלל צריך להשתמש בהם רק ב-MULTIPLE כדי לצמצם את הסוג של רכיב אחר. המפתח FLAG הוא אופציונלי, והברירת המחדל שלו היא true.

    "SAMPLE_ELEMENT": {
      "TYPE": "CLICKABLE",
      "FLAG": false
    }

CLASS

מזהים את הרכיב על סמך הכיתה שלו.

    "SECURITY_SETTINGS_ENTER_PASSWORD": {
      "TYPE": "CLASS",
      "VALUE": "android.widget.EditText"
    }

HAS_ANCESTOR

כדי לזהות את הרכיב, מחפשים את היררכיית הווידג'ט אצל אביו. המפתח ANCESTOR מכיל אובייקט שמזהה את האב. המפתח DEPTH מציין את השלב הבא בהיררכיה שבה צריך לחפש. DEPTH הוא אופציונלי וערך ברירת המחדל שלו הוא 1.

      "SAMPLE_ELEMENT": {
      "TYPE": "HAS_ANCESTOR",
      "DEPTH": 2,
      "ANCESTOR": {
        "TYPE": "CLASS",
        "VALUE": "android.view.ViewGroup"
      }
    }

HAS_DESCENDANT

כדי לזהות את הרכיב, צריך לעבור לאורך ההיררכיה ולבדוק את הצאצאים שלו. המפתח DESCENDANT מכיל אובייקט שמציין את הצאצא שרוצים לחפש. המפתח DEPTH מציין עד כמה גבוה בתוך ההיררכיה צריך לחפש. השדה DEPTH הוא אופציונלי וערך ברירת המחדל שלו הוא 1.

      "SAMPLE_ELEMENT": {
      "TYPE": "HAS_DESCENDANT",
      "DEPTH": 2,
      "DESCENDANT": {
        "TYPE": "CLASS",
        "VALUE": "android.view.ViewGroup"
      }
    }

מרובה

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

      "APP_INFO_SETTINGS_PERMISSION_MANAGER": {
      "TYPE": "MULTIPLE",
      "SPECIFIERS": [
        {
          "TYPE": "CLASS",
          "VALUE": "android.widget.RelativeLayout"
        },
        {
          "TYPE": "HAS_DESCENDANT",
          "MAX_DEPTH": 2,
          "DESCENDANT": {
            "TYPE": "TEXT",
            "VALUE": "Permission manager"
          }
        }
      ]
    }

בדוגמה הזו, ההגדרה מזהה RelativeLayout שיש לו צאצא בעומק 2, עם הטקסט Permission manager.

Workflows

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

    "WORKFLOWS": {
    "OPEN_SOUND_SETTINGS_WORKFLOW": [
      {
        "NAME": "Go to Home",
        "TYPE": "PRESS",
        "CONFIG": {
          "TEXT": "HOME"
        }
      },
      {
        "NAME": "Open Settings",
        "TYPE": "COMMAND",
        "CONFIG": {
          "TEXT": "am start -a android.settings.SETTINGS"
        }
      },
      {
        "NAME": "Open Sound Settings",
        "TYPE": "SCROLL_TO_FIND_AND_CLICK",
        "CONFIG": {
          "UI_ELEMENT": {
            "TYPE": "TEXT",
            "VALUE": "Sound"
          }
        },
        "SCROLL_CONFIG": {
          "SCROLL_ACTION": "USE_GESTURE",
          "SCROLL_DIRECTION": "VERTICAL",
          "SCROLL_ELEMENT": {
            "TYPE": "RESOURCE_ID",
            "VALUE": "car_ui_recycler_view"
          }
        }
      }
    ]
  }

כל תהליך עבודה הוא צמד מפתח/ערך, שבו המפתח הוא שם תהליך העבודה והערך הוא מערך של פעולות לביצוע. לכל פעולה יש NAME, TYPE, (בדרך כלל) CONFIG ו (לפעמים) SWIPE_CONFIG או SCROLL_CONFIG. ברוב סוגי ה-TYPE, ה-CONFIG הוא אובייקט עם מפתח UI_ELEMENT שהערך שלו הוא באותו פורמט כמו הערך של רשומת רכיב ממשק המשתמש (ראו למעלה). סוגי ה-TYPE האלה הם:

PRESS
Long_PRESS
Click
Long_CLICK
CLICK_IF_EXIST
HAS_UI_ELEMENT_IN_FOREGROUND
SCROLL_TO_FIND_AND_CLICK
SCROLL_TO_FIND_AND_CLICK_IF_EXIST
SWIPE_TO_FIND_AND_CLICK
SWIPE_TO_FIND_AND_CLICK_IF_EXIST

בשאר הערכים של TYPE, פרטי ההגדרה הם:

אובייקט תיאור
COMMAND אובייקט עם ערך TEXT שמכיל את הפקודה לביצוע.
HAS_PACKAGE_IN_FOREGROUND אובייקט עם ערך TEXT שמכיל את החבילה.
SWIPE משמיטים את CONFIG key עבור פעולת SWIPE. הקוד הזה משתמש רק ב-SWIPE_CONFIG
WAIT_MS אובייקט עם ערך TEXT שמכיל את מספר אלפיות השנייה שצריך להמתין.

כדי לבצע פעולות שקשורות לגלילה ולהחלקה יש צורך בהגדרות נוספות, כך:

SCROLL_CONFIG

אובייקט תיאור
SCROLL_ACTION USE_GESTURE או USE_BUTTON
SCROLL_DIRECTION HORIZONTAL או VERTICAL
SCROLL_ELEMENT אובייקט שמציין את המאגר שרוצים לגלול, באותו פורמט של הגדרת רכיב בממשק המשתמש (ראו למעלה).
SCROLL_FORWARD, SCROLL_BACKWARD לחצני הגלילה קדימה ואחורה (נדרשים כש-SCROLL_ACTION הוא USE_BUTTON).
SCROLL_MARGIN אם הערך של SCROLL_ACTION הוא USE_GESTURE, המרחק ממרכז המאגר שבו מתחילים ומפסיקים את הגרירה שתשמש לביצוע הגלילה (אופציונלי, ברירת המחדל = 10).
SCROLL_WAIT_TIME אם הערך של SCROLL_ACTION הוא USE_GESTURE, זהו משך הזמן באלפיות שנייה שצריך להמתין בין תנועות הגלילה כשמחפשים אובייקט ללחוץ עליו. (אופציונלי, ברירת המחדל = 1).

SWIPE_CONFIG

אובייקט תיאור
SWIPE_DIRECTION TOP_TO_BOTTOM,‏ BOTTOM_TO_TOP,‏ LEFT_TO_RIGHT או RIGHT_TO_LEFT
SWIPE_FRACTION

אחת מהאפשרויות הבאות:

  • FULL: מחליקים מהקצה האחד של המסך לקצה השני

    לחלופין,
  • DEFAULT: מקצה המסך לקצה המסך, עם מאגר של חמישה (5) פיקסלים בכל צד.

    OR
  • THREE_QUARTER,‏ HALF או QUARTER: תנועת החלקה מסתיימת חמישה (5) פיקסלים ממרכז המסך, ומתחילה בנקודה כך שהיא מכסה את המרחק שצוין במסך.
NUMBER_OF_STEPS מספר השלבים לביצוע החלקה. פרטים נוספים זמינים ב segmentSteps.

פיתוח והפעלה

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

דוגמת הקוד הבאה מציגה את הבנייה, ההתקנה וההפעלה של APK לבדיקה.

# Build Test APK
make TEST-APK-NAME
# Install Test APK
adb -s DEVICE-SERIAL install -r PATH-FOR-BUILT-TEST-APK
# Execute Test with the JSON file
adb -s DEVICE-SERIAL shell am instrument -w -r -e debug false -e config-file-path /data/local/tmp/jsonFile.json -e class TEST-PACKAGE.TEST-CLASSNAME TEST-PACKAGE/androidx.test.runner.AndroidJUnitRunner

בפקודות האלה:

  • TEST-APK-NAME: השם של האפליקציה שרוצים לבדוק. לדוגמה, מגדירים את TEST-APK-NAME כ-AndroidAutomotiveSettingsTests כדי לבדוק את הגדרות ה-Wi-Fi כפי שצוינו בקובץ Android.bp. תוכלו למצוא את שם ה-APK בקובץ Android.bp המתאים של בדיקת כלי רכב.

  • DEVICE-SERIAL: המזהה הסידורי של ה-DUT. הפרמטר הזה לא נדרש אם רק מכשיר אחד מחובר למארח.

  • config-file-path: פרמטר אופציונלי שנדרש רק כדי לספק הגדרות של ממשק המשתמש של המכשיר שאינן ברירת המחדל, כפי שצוין בקובץ התצורה בפורמט JSON. אם לא מציינים את הפרמטרים האלה, המערכת תשתמש בערכי ברירת המחדל להרצת הבדיקות.

  • PATH-FOR-BUILT-TEST-APK: הנתיב שבו נוצר קובץ ה-APK לבדיקה כשמפעילים את הפקודה make.

  • TEST-PACKAGE: השם של חבילת הבדיקה.

  • TEST-CLASSNAME: השם של מחלקת הבדיקה. לדוגמה, בבדיקה Wifi Settings, שם החבילה הוא android.platform.tests ושם הכיתה של הבדיקה הוא WifiSettingTest.

ספריית קטעי מידע על רכבים

ספריית Automotive Snippet היא קבוצה של ספריות בדיקה של Android לפרויקט Android Open Source Project‏ (AOSP), שנועדו לתקשר עם אפליקציות ושירותים לכלי רכב. הוא משתמש ב-Spectatio עם מנגנון נוח לביצוע קריאות לפעולות מרחוק (RPCs) ממכונה מארח (בדיקה) למכשיר מבוסס Android.

שנתחיל?

לפני שמתחילים, כדאי לעיין בקטעים הבאים.

דרישות מוקדמות

  • Python 3.x מותקן במכונה המארחת.
  • הגדרת סביבה של AOSP עם כלי ה-build הנדרשים.
  • מכשיר Android לכלי רכב (מכונה וירטואלית או מכשיר פיזי) עם גישה ל-adb.

קומפילציה

כדי לקמפל את קטעי הקוד השונים שסופקו על ידי ספריית הקטעים לכלי רכב, תוכלו להשתמש בקובץ android.bp שסופק. פועלים לפי הפקודות בקטע הקודם כדי לקמפל את קובץ ה-APK.

פריסה

אחרי שמאגרי ה-snippets יקובצו, אפשר לפרוס את חבילות ה-APK שנוצרו במכשיר היעד באמצעות הפקודה adb install שצוינה בקטע הקודם.

הרצת בדיקות

ספריות קטעי הקוד חושפות כמה שיטות RPC לאינטראקציה עם מערכת הרכב. אפשר להפעיל את השיטות האלה דרך מסגרת Mobly מהמכונה המארחת. בהנחה שהגדרתם את סביבת הבדיקה של Mobly, תוכלו להשתמש בסקריפט snippet_shell.py כדי לפתוח מעטפת Python אינטראקטיבית, שבה תוכלו להפעיל באופן ידני שיטות RPC במכשיר. דוגמה להפעלה:

python3 snippet_shell.py com.google.android.mobly.snippet.bundled -s <serial>

מחליפים את <serial> במספר הסידורי של המכשיר. אם יש כמה מכשירים מחוברים, אפשר לקבל את המספר באמצעות adb devices.

ספריות כלולות

ספריית הקטעים לכלי רכב כוללת את ספריות הקטעים ואת הספריות העזר הבאות:

  • AutomotiveSnippet: ממשקי API שקשורים לפעולות ברכב, כמו חיוג, בקרת עוצמת קול, מקשים פיזיים ברכב ואינטראקציה עם מרכז המדיה.

  • PhoneSnippet: ממשקי API שקשורים לטלפוניה, כולל טיפול בשיחות, גלישה באנשי קשר ופעולות של שליחת הודעות SMS.

לקטע הקוד לכלי רכב ולקטע הקוד PhoneSnippet יש לוגיקה משותפת מסוימת. באופן ספציפי, אפשר לפרוץ לשיחות RCP שקשורות ל-Bluetooth כדי להתאים מכשיר רכב למכשיר טלפון. bt_discovery_test מראה איך עושים את זה.