Spectatio: Automotive 測試架構

Spectatio 是開放原始碼測試架構,可在實體和虛擬裝置上測試 Android Automotive OS (AAOS)。Spectatio 提供 API,可用於在汽車裝置上測試應用程式,這項可擴充且可調整的解決方案可用於驗證 AAOS 及其應用程式的功能和效能。

整體設計

Spectatio 架構可配合各種 AAOS UI 實作方式調整及擴充。可用於測試裝置硬體、模擬器和虛擬化環境中 AAOS 的功能和效能。

下圖說明 Spectatio 架構的大致設計。

Spectatio 架構高階設計

圖 1. Spectatio 架構高階設計。

Spectatio 架構是建構在 UI Automator 之上,提供一組 API,用於建構可與 AAOS 上的使用者和系統應用程式互動的 UI 測試。汽車測試會使用 Spectatio 架構提供的 API 進行測試,讓這些測試不受測試裝置 (DUT) 影響,並可擴展至測試各種裝置 (如有支援)。

如圖 1 所示,Spectatio 架構是根據參考應用程式 (例如撥號、Medicenter 和設定) 模組化,使用應用程式專屬介面和輔助程式,讓新應用程式可輕鬆擴充。Spectatio 架構會重複使用常見的標準和公用輔助類別。標準輔助程式類別是所有應用程式輔助函式的父類別,可提供特定裝置或跨應用程式適用的標準函式。公用程式輔助類別提供公用程式,例如從裝置讀取或寫入檔案。

建築

為了提供一組 API 來建構 UI 測試,Spectatio 架構會實作應用程式專屬介面和輔助程式,同時擴充現有的標準輔助程式類別,並匯入公用程式輔助程式類別。

圖 2 說明 Spectatio 架構的大致架構,以及實作應用程式測試 API 時涉及的所有實體。

Spectatio 架構高階架構

圖 2. Spectatio 架構高層級架構。

應用程式輔助程式介面會提供應用程式輔助程式實作的藍圖。其中包含各種輔助函式,可用於測試應用程式。每個應用程式都有自己的介面,例如 IAutoSettingHelperIAutoDialHelper。如需進一步瞭解相關資訊和介面函式清單,請參閱 AOSP 上的應用程式輔助程式介面函式

標準輔助程式類別包含裝置設定所需的標準屬性和函式,但不限於任何應用程式,例如 pressHomescroll。標準輔助類別是在 AbstractAutoStandardAppHelper.java 中定義。

架構會使用公用程式輔助類別。舉例來說,AutoJsonUtility.java 是實用程式類別,可載入指定裝置的 JSON 設定檔,並在執行階段更新架構設定。

應用程式輔助程式實作模組是 Spectatio 架構的核心。其中包含應用程式輔助程式介面中定義的輔助函式實作項目,這些項目是測試汽車裝置上的應用程式所需的。每個應用程式都有自己的實作方式,例如 SettingHelperImplDialHelperImpl,Automotive 測試會使用這些實作方式來測試應用程式。如需更多資訊和實作清單,請參閱 AOSP 中的「應用程式輔助程式實作函式」。

Automotive 測試會使用應用程式輔助程式實作函式,測試與應用程式相關的各種作業。請使用 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());
 
}
}

自訂

Spectatio 架構不受裝置 UI 影響,因此可用於測試具有不同 UI 和硬體的裝置。為達到這種可擴充性,Spectatio 會根據參考裝置使用預設的裝置設定。為支援非預設裝置設定,架構會在執行階段使用 JSON 設定檔,為裝置設定所需的 UI 變更。JSON 設定檔支援 TEXTDESCRIPTIONRESOURCE_ID 等 UI 元素,以及 path 設定,且只能包含與 DUT 的 UI 變更相關的資訊。其餘 UI 元素則會使用架構中提供的預設設定值。

預設裝置設定

以下 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 上依序前往「設定」>「系統」>「日期和時間」

// 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:受測物件的序號 ID。如果只有一個裝置連線至主機,則不需要這個參數。

  • PATH-TO-JSON-FILE:主機上的 JSON 檔案路徑。

設定格式

設定中包含五個頂層物件,其中包含下列鍵和值:

物件 說明
PACKAGES 描述各種應用程式主要套件的物件,用於判斷該應用程式是否處於前景。
ACTIONS 表示各種動作的動作類型和參數的物件。例如,要使用按鈕還是手勢來捲動畫面。
COMMANDS 指定執行各種動作的指令的物件。
UI_ELEMENTS 用於建構 UI Automator `BySelectors` 的物件,可用來選取 UI 元素 (詳情請見下文)。
WORKFLOWS 可完成高階工作 (詳見下文) 的動作序列。

UI 元素

每個 UI 元素都有一個 TYPE,可指定 UI Automator 會尋找哪些元素 (例如資源 ID、文字和說明),以及與該類型相關聯的設定值。一般來說,只要輔助程式使用此設定來識別畫面上的元素,就會取得確切的一個元素。如果有多個元素符合設定,測試中會使用任意一個元素。因此,設定 (通常) 應以足夠明確的方式編寫,以便在相關情境中縮小至一個元素。

文字

這是最簡單的 UI 元素類型。系統會根據 UI 元素的文字來識別該元素,且必須完全相符。

    "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

透過資源 ID 識別元素,並視需要檢查該 ID 的套件元件。PACKAGE 鍵為選用項目;如果省略,系統會比對任何套件,並只考慮 :id/ 後面的 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"
     
}
   
}

MULTIPLE

根據多個同時條件找出元素,且所有條件都必須符合。

      "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": {
   
"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"
         
}
       
}
     
}
   
]
 
}

每個工作流程都是鍵/值組合,其中鍵是工作流程的名稱,值則是要執行的動作陣列。每項動作都有 NAMETYPE、(通常) CONFIG,以及 (有時) SWIPE_CONFIGSCROLL_CONFIG。對於大多數 TYPE,CONFIG 是具有 UI_ELEMENT 鍵的物件,其值的格式與 UI 元素項目相同 (請見上文)。這些 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_GESTUREUSE_BUTTON
SCROLL_DIRECTION HORIZONTALVERTICAL
SCROLL_ELEMENT 物件,用來指出要捲動的容器,使用與 UI 元素設定相同的格式 (請參閱上方說明)。
SCROLL_FORWARDSCROLL_BACKWARD 向前和向後捲動按鈕 (當 SCROLL_ACTIONUSE_BUTTON 時,此按鈕為必填)。
SCROLL_MARGIN 如果 SCROLL_ACTIONUSE_GESTURE,則表示從容器邊緣開始和停止拖曳的距離,用於執行捲動 (選用,預設值 = 10)。
SCROLL_WAIT_TIME 如果 SCROLL_ACTIONUSE_GESTURE,則在搜尋要點選的物件時,捲動手勢之間的等待時間 (以毫秒為單位)。(選用,預設值 = 1)。

SWIPE_CONFIG

物件 說明
SWIPE_DIRECTION TOP_TO_BOTTOMBOTTOM_TO_TOPLEFT_TO_RIGHTRIGHT_TO_LEFT
SWIPE_FRACTION

下列任一項:

  • FULL:從螢幕邊緣向兩側滑動

  • DEFAULT:從螢幕邊緣到螢幕邊緣,每側有五 (5) 個像素緩衝區。

  • THREE_QUARTERHALFQUARTER:滑動手勢會在離螢幕邊緣五 (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,即可測試 Android.bp 檔案中指定的 Wi-Fi 設定。您可以在汽車測試的對應 Android.bp 檔案中找到 APK 名稱。

  • DEVICE-SERIAL:受測物件的序號 ID。如果只有一個裝置連線到主機,則不需要這個參數。

  • config-file-path:選用參數,僅需在 JSON 設定檔中指定非預設裝置 UI 設定時才需要。如未提供,架構會使用預設值執行測試。

  • PATH-FOR-BUILT-TEST-APK:執行 make 指令時,測試 APK 的建構路徑。

  • TEST-PACKAGE:測試套件的名稱。

  • TEST-CLASSNAME:測試類別的名稱。舉例來說,對於 Wifi 設定測試,測試套件為 android.platform.tests,測試類別名稱為 WifiSettingTest

汽車摘要程式庫

Automotive Snippet Library 是一系列 Android 測試程式庫,適用於 Android 開放原始碼計畫 (AOSP),旨在與汽車應用程式和服務互動。它利用 Spectatio 提供的便利機制,從主機 (測試) 機器執行遠端程序呼叫 (RPC),傳送至搭載 Android 的裝置。

開始使用

開始前,請先詳閱下列各節。

必要條件

  • 主機上已安裝 Python 3.x。
  • 設定 AOSP 環境,並安裝必要的建構工具。
  • 具備 ADB 存取權的 Android 車用裝置 (模擬器或實體裝置)。

編譯

如要編譯 Automotive 程式碼片段庫提供的各種程式碼片段,您可以使用提供的 android.bp 檔案。按照上一節中的指令編譯 APK。

部署作業

成功編譯程式片段程式庫後,請使用前一個章節提到的 adb install 指令,將產生的 APK 部署至目標裝置。

執行測試

程式碼片段程式庫會公開多種 RPC 方法,用於與汽車系統互動。這些方法可透過主機機器的 Mobly 架構來叫用。假設您已設定 Mobly 測試環境,就可以使用 snippet_shell.py 指令碼開啟互動式 Python 殼層,在其中手動叫用裝置上的 RPC 方法。叫用方式範例:

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

<serial> 替換為裝置序號,如果連接多部裝置,您可以使用 adb devices 取得序號。

內含程式庫

Automotive 程式片段程式庫包含下列程式片段程式庫和輔助程式:

  • AutomotiveSnippet:提供與車輛操作相關的 API,例如撥號、音量控制、車輛實體鍵和媒體中心互動。

  • PhoneSnippet:提供與電話相關的 API,包括通話處理、聯絡人瀏覽和簡訊作業。

Automotive 程式碼片段和 PhoneSnippet 程式碼片段共用一些共同的邏輯。具體來說,您可以侵入藍牙相關的 RCP 呼叫,以便將汽車和手機裝置配對。這個 bt_discovery_test 會說明如何操作。