Spectatio — это платформа тестирования с открытым исходным кодом, разработанная для тестирования Android Automotive OS (AAOS) на реальных и виртуальных устройствах. Spectatio предоставляет API для тестирования приложений на автомобильном устройстве и представляет собой расширяемое и масштабируемое решение, используемое для проверки возможностей и производительности AAOS и его приложений.
Дизайн высокого уровня
Платформа Spectatio адаптируется и расширяется для различных реализаций пользовательского интерфейса AAOS. Он используется для тестирования возможностей и производительности AAOS на аппаратном обеспечении устройств, эмуляторах и виртуализированных средах.
На следующем рисунке поясняется высокоуровневый дизайн платформы Spectatio.
Рисунок 1. Высокоуровневый проект платформы Spectatio.
Платформа Spectatio, созданная на основе UI Automator , предоставляет набор API для создания тестов пользовательского интерфейса, которые взаимодействуют с пользовательскими и системными приложениями в AAOS. В автомобильных тестах используются API-интерфейсы, предоставляемые платформой Spectatio для тестирования, что делает эти тесты независимыми от тестируемого устройства (DUT) и масштабируемыми для тестирования различных устройств, если они поддерживаются.
На рисунке 1 показано, что платформа Spectatio имеет модульную структуру на основе эталонных приложений, таких как Dialer, Medicenter и Settings, с использованием интерфейсов и помощников для конкретных приложений, что позволяет легко расширять ее для новых приложений. Платформа Spectatio повторно использует общие стандартные и служебные вспомогательные классы. Стандартный вспомогательный класс является родительским классом для всех вспомогательных функций приложения и предоставляет стандартные функции, специфичные для устройства или применимые ко всем приложениям. Вспомогательные классы утилит предоставляют такие утилиты, как чтение или запись файлов с устройства.
Архитектура
Чтобы предоставить набор API-интерфейсов для создания тестов пользовательского интерфейса, платформа Spectatio реализует интерфейсы и помощники для конкретных приложений, одновременно расширяя существующий стандартный вспомогательный класс и импортируя служебные вспомогательные классы.
На рис. 2 показана высокоуровневая архитектура платформы Spectatio и все объекты, участвующие в реализации API для тестирования приложения.
Рисунок 2. Архитектура высокого уровня платформы Spectatio.
Интерфейс помощника приложения предоставляет схему реализации помощника приложения. Он состоит из различных вспомогательных функций, необходимых для тестирования приложений. Каждое приложение имеет собственный интерфейс, например IAutoSettingHelper
и IAutoDialHelper
. Дополнительную информацию и список функций интерфейса см. в разделе Функции интерфейса помощника приложения на AOSP.
Стандартный вспомогательный класс состоит из стандартных атрибутов и функций, которые необходимы для настройки устройства, но не относятся к какому-либо приложению, например pressHome
и scroll
. Стандартный вспомогательный класс определен в AbstractAutoStandardAppHelper.java
.
Вспомогательные классы утилиты используются платформой. Например, AutoJsonUtility.java
— это служебный класс, который загружает заданный файл конфигурации JSON устройства и обновляет конфигурации платформы во время выполнения.
Модуль реализации помощника приложения является ядром платформы Spectatio. Он содержит реализацию вспомогательных функций, определенных в вспомогательном интерфейсе приложения, которые необходимы для тестирования приложений на автомобильном устройстве. Каждое приложение имеет собственную реализацию, например SettingHelperImpl
и DialHelperImpl
, используемые автомобильными тестами для тестирования приложений. Дополнительные сведения и список реализаций см. в разделе «Функции реализации помощника приложения » на 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());
}
}
Кастомизация
Платформа Spectatio не зависит от пользовательского интерфейса устройства, поэтому ее можно масштабировать для тестирования устройств с различными пользовательскими интерфейсами и оборудованием. Для достижения такой масштабируемости Spectatio использует конфигурации устройств по умолчанию на основе эталонного устройства. Для поддержки конфигураций устройств, отличных от настроек по умолчанию, платформа использует файл конфигурации JSON во время выполнения, чтобы задать желаемые изменения пользовательского интерфейса для устройства. Файл конфигурации JSON поддерживает такие элементы пользовательского интерфейса, как TEXT
, DESCRIPTION
и RESOURCE_ID
, а также настройки path
и должен содержать только информацию об изменениях пользовательского интерфейса для тестируемого устройства. Остальные элементы пользовательского интерфейса используют значения конфигурации по умолчанию, предусмотренные в платформе.
Конфигурации устройств по умолчанию
В следующем примере файла конфигурации 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, в котором настройки по умолчанию переопределяются настройками тестируемого устройства. В этом примере:
Настройки Интернета называются «Сеть и Интернет» на эталонных устройствах и «Подключение» на тестируемом устройстве.
Настройки даты и времени доступны в меню «Настройки» > «Дата и время» для эталонных устройств и в «Настройки» > «Система» > «Дата и время» для тестируемого устройства.
// 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 : Серийный идентификатор тестируемого устройства. Этот параметр не требуется, если к хосту подключено только одно устройство.
PATH-TO-JSON-FILE : путь к файлу JSON на хост-компьютере.
Формат конфигурации
В конфигурации имеется пять объектов верхнего уровня со следующими ключами и значениями:
Объект | Описание |
---|---|
PACKAGES | Объект, описывающий основной пакет для различных приложений, который используется для определения того, когда это приложение находится на переднем плане. |
ACTIONS | Объект, указывающий типы действий и параметры для различных действий. Например, использовать ли кнопки или жест для прокрутки. |
COMMANDS | Объект, определяющий команды, выполняющие различные действия. |
UI_ELEMENTS | Объект, используемый для создания UI Automator BySelectors, который выбирает элементы пользовательского интерфейса (подробно описано ниже). |
WORKFLOWS | Последовательность действий, выполняющих задачи высокого уровня (подробно описанные ниже). |
элементы пользовательского интерфейса
Каждый элемент пользовательского интерфейса имеет TYPE
, который определяет, что UI Automator будет искать для идентификации элемента (например, идентификатор ресурса, текст и описание) и значений конфигурации, связанных с этим типом. В общем, всякий раз, когда помощник идентифицирует элемент на экране, используя эту конфигурацию, он получает ровно один элемент. Если конфигурации соответствуют несколько элементов, в тесте используется произвольный. Следовательно, конфигурация должна (как правило) быть написана достаточно конкретно, чтобы она сводилась к одному элементу в соответствующем контексте.
ТЕКСТ
Это самый простой тип элемента пользовательского интерфейса. Элемент пользовательского интерфейса идентифицируется по тексту и требует точного совпадения.
"CALL_HISTORY_MENU": {
"TYPE": "TEXT",
"VALUE": "Recents"
}
ТЕКСТ_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": {
"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
, значение которого принимает ту же форму, что и запись элемента пользовательского интерфейса (см. выше). Эти ТИПЫ:
НАЖИМАТЬ LONG_PRESS НАЖМИТЕ 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_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 база кода 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 : серийный идентификатор тестируемого устройства. Этот параметр не требуется, если к хосту подключено только одно устройство.
config-file-path
: необязательный параметр, который необходим только для предоставления конфигураций пользовательского интерфейса устройства, отличных от стандартных, как указано в файле конфигурации JSON . Если этот параметр не указан, платформа использует значения по умолчанию для выполнения тестов.PATH-FOR-BUILT-TEST-APK : путь, по которому создается тестовый APK при выполнении команды
make
.TEST-PACKAGE : Имя тестового пакета.
TEST-CLASSNAME : Имя тестового класса. Например, для теста настроек Wi-Fi тестовый пакет —
android.platform.tests
, а имя тестового класса —WifiSettingTest
.
Библиотека автомобильных фрагментов
Библиотека автомобильных фрагментов — это набор тестовых библиотек Android для проекта Android с открытым исходным кодом (AOSP), предназначенных для взаимодействия с автомобильными приложениями и службами. Он использует Spectatio с удобным механизмом выполнения удаленных вызовов процедур (RPC) с хост-машины (тестовой) на устройство под управлением Android.
Начать
Прежде чем начать, просмотрите эти разделы.
Предварительные условия
- Python 3.x установлен на хост-компьютере.
- Настройка среды AOSP с необходимыми инструментами сборки.
- Автомобильное устройство Android (эмулятор или физическое устройство) с доступом к adb.
Сборник
Чтобы скомпилировать различные фрагменты, предоставленные Библиотекой автомобильных фрагментов, вы можете использовать предоставленный файл android.bp
. Следующие команды из предыдущего раздела для компиляции APK.
Развертывание
После успешной компиляции библиотек фрагментов разверните полученные APK-файлы на целевом устройстве с помощью команды adb install
упомянутой в предыдущем разделе.
Запуск тестов
Библиотеки фрагментов предоставляют несколько методов RPC для взаимодействия с автомобильной системой. Эти методы можно вызывать через платформу Mobly с хост-компьютера. Предполагая, что у вас настроена тестовая среда Mobly, вы можете использовать сценарий snippet_shell.py
, чтобы открыть интерактивную оболочку Python, где вы можете вручную вызывать методы RPC на устройстве. Пример вызова:
python3 snippet_shell.py com.google.android.mobly.snippet.bundled -s <serial>
Замените <serial>
серийным номером устройства, который вы можете получить с помощью устройств adb, если подключено несколько устройств.
Включенные библиотеки
Библиотека автомобильных фрагментов включает в себя следующие библиотеки фрагментов и помощники:
AutomotiveSnippet: предоставляет API-интерфейсы, связанные с операциями автомобиля, такими как набор номера, регулировка громкости, аппаратные клавиши автомобиля и взаимодействие с медиацентром.
PhoneSnippet: предоставляет API-интерфейсы, связанные с телефонией, включая обработку вызовов, просмотр контактов и операции с SMS.
Фрагмент Automotive и PhoneSnippet имеют общую логику. В частности, вы можете вторгаться в вызовы RCP, связанные с Bluetooth, для сопряжения автомобиля и телефонного устройства. Этот bt_discovery_test
показывает, как это сделать.
- TEST-CLASSNAME : Имя тестового класса. Например, для теста настроек Wi-Fi тестовый пакет —
android.platform.tests
, а имя тестового класса —WifiSettingTest
.