Spectatio היא מסגרת בדיקה בקוד פתוח שפותחה במיוחד לצורך בדיקות ל-Android Automotive OS (AAOS) במכשירים וירטואליים ובמכשירים אמיתיים. Spectatio מספק ממשקי API עבור בדיקת אפליקציות במכשיר כלי רכב, וזהו פתרון ניתן להרחבה שניתן להתאמה משמש לאימות היכולת והביצועים של AAOS ושל האפליקציות שלו.
העיצוב הכללי
ה-framework של Spectatio ניתן להתאמה ולהרחבה לממשקי משתמש שונים של AAOS בפועל. הוא משמש לבדיקת היכולת והביצועים של AAOS בחומרה, באמולטורים ובסביבות וירטואליות של המכשירים.
האיור הבא מסביר את העיצוב הכללי של מסגרת 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 לבדיקת אפליקציה.
איור 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 |
אחת מהאפשרויות הבאות:
|
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
מוסבר איך עושים את זה.
- TEST-CLASSNAME: השם של כיתת הבדיקה. לדוגמה, עבור
בדיקת הגדרות ה-Wi-Fi,
חבילת הבדיקה היא
android.platform.tests
ושם כיתת הבדיקה הואWifiSettingTest
.