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

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

העיצוב הכללי

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

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

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

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

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

איור 1 מראה שמסגרת Spectatio עוברת מודולריזציה על סמך הפניה אפליקציות כמו 'חייגן', Medicenter והגדרות שמשתמשות באפליקציות ספציפיות ממשקים וכלים מסייעים, כך שניתן להרחיב אותו בקלות לאפליקציות חדשות. הספקטאטיו של framework עושה שימוש חוזר במחלקות הנפוצות של Standard (standard) ו-תוכנית עזר של שירותים. כיתת עוזר/ת רגיל/ת היא מחלקת ההורה של כל הפונקציות של העוזרים לאפליקציות, פונקציות רגילות שהן ספציפיות למכשיר או רלוונטיות בכל האפליקציות. כיתות עזרי שירותים מספקים כלים כמו קריאה או כתיבה של קבצים מהמכשיר.

ארכיטקטורה

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

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

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

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

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

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

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

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

בדיקות כלי רכב להשתמש בפונקציות ההטמעה של כלי העזר לאפליקציה כדי לבדוק פעולות שונות שקשורות לאפליקציה. שימוש בכיתה 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 משתמש בתצורות ברירת המחדל של המכשיר בהתאם למכשיר העזר. שפת תרגום לא תומכת בתצורות מכשירים שאינן ברירת המחדל, ה-framework משתמש ב-JSON בקובץ התצורה בזמן הריצה, כדי להגדיר את השינויים הרצויים בממשק המשתמש של המכשיר. א' קובץ התצורה של JSON תומך ברכיבי ממשק משתמש כמו TEXT, DESCRIPTION וגם RESOURCE_ID, וגם ההגדרות של path, וחייבים להכיל רק את המידע על השינויים בממשק המשתמש של ה-DUT. בשאר הרכיבים של ממשק המשתמש משתמשים בברירת המחדל וערכי התצורה שסופקו ב-framework.

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

בדוגמה הבאה של קובץ תצורת 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. בדוגמה הזו:

  • השם של הגדרות האינטרנט הוא Network & אינטרנט במכשירי עזר קישוריות ב-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' של ממשק המשתמש הרכיבים (כפי שמפורט בהמשך).
WORKFLOWS רצפים של פעולות שמבצעות משימות ברמה גבוהה (מתוארות בקטע בהמשך).

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

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

טקסט

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

    "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
    }

כיתה

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

    "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

פרטי ההגדרות האישיות האחרים הם:

אובייקט תיאור
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) מאגר פיקסלים בכל צד.

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

פיתוח והפעלה

מסגרת Spectatio נוצרת באופן אוטומטי כחלק מחבילת ה-APK לבדיקה. כדי ליצור את ה-APK לבדיקה, ה-codebase של 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 . אם לא תספקו כתובת, framework משתמש בערכי ברירת מחדל לביצוע הבדיקות.

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

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

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

ספריית קטעי הקוד של כלי רכב

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

שנתחיל?

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

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

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

קומפילציה

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

פריסה

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

הרצת בדיקות

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

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

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

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

ספריית קטעי הקוד של כלי רכב כוללת את ספריות קטעי הקוד הבאות וגם את helpers:

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

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

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