Spectatio — это тестовая среда с открытым исходным кодом, разработанная для тестирования Android Automotive OS (AAOS) на реальных и виртуальных устройствах. Spectatio предоставляет API для тестирования приложений на автомобильном устройстве и является расширяемым и масштабируемым решением, используемым для проверки возможностей и производительности AAOS и ее приложений.
Высокоуровневый дизайн
Фреймворк Spectatio адаптируем и расширяем для различных реализаций пользовательского интерфейса AAOS. Он используется для тестирования возможностей и производительности AAOS на аппаратном обеспечении устройств, эмуляторах и виртуализированных средах.
На следующем рисунке поясняется высокоуровневая структура фреймворка Spectatio.
Рисунок 1. Высокоуровневая конструкция фреймворка Spectatio.
Созданный на основе UI Automator , фреймворк Spectatio предоставляет набор 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.
Automotive Tests используют функции реализации помощника приложения для тестирования различных операций, связанных с приложением. Используйте класс 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
и должен содержать только информацию об изменениях пользовательского интерфейса для DUT. Остальные элементы пользовательского интерфейса используют значения конфигурации по умолчанию, предоставленные в фреймворке.
Конфигурации устройства по умолчанию
В следующем примере файла конфигурации JSON показаны доступные конфигурации устройств и их значения по умолчанию.
Нажмите здесь, чтобы отобразить пример файла конфигурации JSON.
{ "SETTINGS": { "APPLICATION_CONFIG": { "SETTINGS_TITLE_TEXT": "Settings", "SETTINGS_PACKAGE": "com.android.car.settings", "SETTINGS_RRO_PACKAGE": "com.android.car.settings.googlecarui.rro", "OPEN_SETTINGS_COMMAND": "am start -a android.settings.SETTINGS", "OPEN_QUICK_SETTINGS_COMMAND": "am start -n com.android.car.settings/com.android.car.settings.common.CarSettingActivity" }, "QUICK_SETTINGS": { "OPEN_MORE_SETTINGS": { "TYPE": "RESOURCE_ID", "VALUE": "toolbar_menu_item_1", "PACKAGE": "com.android.car.settings" }, "NIGHT_MODE": { "TYPE": "TEXT", "VALUE": "Night mode" } }, "DISPLAY": { "PATH": "Settings > Display", "OPTIONS": [ "Brightness level" ], "BRIGHTNESS_LEVEL": { "TYPE": "RESOURCE_ID", "VALUE": "seekbar", "PACKAGE": "com.android.car.settings" } }, "SOUND": { "PATH": "Settings > Sound", "OPTIONS": [ "Media volume", "Alarm volume" ] }, "NETWORK_AND_INTERNET": { "PATH": "Settings > Network & internet", "OPTIONS": [ ], "TOGGLE_WIFI": { "TYPE": "RESOURCE_ID", "VALUE": "master_switch", "PACKAGE": "com.android.car.settings" } }, "BLUETOOTH": { "PATH": "Settings > Bluetooth", "OPTIONS": [ ], "TOGGLE_BLUETOOTH": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_menu_item_switch", "PACKAGE": "com.android.car.settings" } }, "APPS_AND_NOTIFICATIONS": { "PATH": "Settings > Apps & notifications", "OPTIONS": [ ], "SHOW_ALL_APPS": { "TYPE": "TEXT", "VALUE": "Show all apps" }, "ENABLE_DISABLE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_menu_item_text", "PACKAGE": "com.android.car.settings" }, "DISABLE_BUTTON_TEXT": { "TYPE": "TEXT", "VALUE": "Disable" }, "ENABLE_BUTTON_TEXT": { "TYPE": "TEXT", "VALUE": "Enable" }, "DISABLE_APP_BUTTON": { "TYPE": "TEXT", "VALUE": "DISABLE APP" }, "FORCE_STOP_BUTTON": { "TYPE": "TEXT", "VALUE": "Force stop" }, "OK_BUTTON": { "TYPE": "TEXT", "VALUE": "OK" }, "PERMISSIONS_MENU": { "TYPE": "TEXT", "VALUE": "Permissions" }, "ALLOW_BUTTON": { "TYPE": "TEXT", "VALUE": "Allow" }, "DENY_BUTTON": { "TYPE": "TEXT", "VALUE": "Deny" }, "DENY_ANYWAY_BUTTON": { "TYPE": "TEXT", "VALUE": "Deny anyway" } }, "DATE_AND_TIME": { "PATH": "Settings > Date & time", "OPTIONS": [ "Automatic date & time", "Automatic time zone" ], "AUTOMATIC_DATE_AND_TIME": { "TYPE": "TEXT", "VALUE": "Automatic date & time" }, "AUTOMATIC_TIME_ZONE": { "TYPE": "TEXT", "VALUE": "Automatic time zone" }, "SET_DATE": { "TYPE": "TEXT", "VALUE": "Set date" }, "SET_TIME": { "TYPE": "TEXT", "VALUE": "Set time" }, "SELECT_TIME_ZONE": { "TYPE": "TEXT", "VALUE": "Select time zone" }, "USE_24_HOUR_FORMAT": { "TYPE": "TEXT", "VALUE": "Use 24-hour format" }, "OK_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "toolbar_menu_item_0", "PACKAGE": "com.android.car.settings" }, "NUMBER_PICKER_WIDGET": { "TYPE": "CLASS", "VALUE": "android.widget.NumberPicker" }, "EDIT_TEXT_WIDGET": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" } }, "USERS": { "PATH": "Settings > Users", "OPTIONS": [ "Guest" ] }, "ACCOUNTS": { "PATH": "Settings > Accounts", "OPTIONS": [ "Automatically sync data" ], "ADD_ACCOUNT": { "TYPE": "TEXT", "VALUE": "ADD ACCOUNT" }, "ADD_GOOGLE_ACCOUNT": { "TYPE": "TEXT", "VALUE": "Google" }, "SIGN_IN_ON_CAR_SCREEN": { "TYPE": "TEXT", "VALUE": "Sign in on car screen" }, "GOOGLE_SIGN_IN_SCREEN": { "TYPE": "TEXT", "VALUE": "Sign in to your Google Account" }, "ENTER_EMAIL": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" }, "ENTER_PASSWORD": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" }, "NEXT_BUTTON": { "TYPE": "TEXT", "VALUE": "Next" }, "DONE_BUTTON": { "TYPE": "TEXT", "VALUE": "Done" }, "REMOVE_BUTTON": { "TYPE": "TEXT", "VALUE": "Remove" }, "REMOVE_ACCOUNT_BUTTON": { "TYPE": "TEXT", "VALUE": "Remove Account" } }, "SYSTEM": { "PATH": "Settings > System", "OPTIONS": [ "About", "Legal information" ], "ABOUT_MENU": { "TYPE": "TEXT", "VALUE": "About" }, "RESET_OPTIONS_MENU": { "TYPE": "TEXT", "VALUE": "Reset options" }, "LANGUAGES_AND_INPUT_MENU": { "TYPE": "TEXT", "VALUE": "Languages & input" }, "DEVICE_MODEL": { "TYPE": "TEXT", "VALUE": "Model" }, "ANDROID_VERSION": { "TYPE": "TEXT", "VALUE": "Android version" }, "ANDROID_SECURITY_PATCH_LEVEL": { "TYPE": "TEXT", "VALUE": "Android security patch level" }, "KERNEL_VERSION": { "TYPE": "TEXT", "VALUE": "Kernel version" }, "BUILD_NUMBER": { "TYPE": "TEXT", "VALUE": "Build number" }, "RECYCLER_VIEW_WIDGET": { "TYPE": "CLASS", "VALUE": "androidx.recyclerview.widget.RecyclerView" }, "RESET_NETWORK": { "TYPE": "TEXT", "VALUE": "Reset network" }, "RESET_SETTINGS": { "TYPE": "TEXT", "VALUE": "RESET SETTINGS" }, "RESET_APP_PREFERENCES": { "TYPE": "TEXT", "VALUE": "Reset app preferences" }, "RESET_APPS": { "TYPE": "TEXT", "VALUE": "RESET APPS" }, "LANGUAGES_MENU": { "TYPE": "TEXT", "VALUE": "Languages" }, "LANGUAGES_MENU_IN_SELECTED_LANGUAGE": { "TYPE": "TEXT", "VALUE": "Idiomas" } }, "SECURITY": { "PATH": "Settings > Security", "OPTIONS": [ ], "TITLE": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_title", "PACKAGE": "com.android.car.settings.googlecarui.rro" }, "CHOOSE_LOCK_TYPE": { "TYPE": "TEXT", "VALUE": "Choose a lock type" }, "LOCK_TYPE_PASSWORD": { "TYPE": "TEXT", "VALUE": "Password" }, "LOCK_TYPE_PIN": { "TYPE": "TEXT", "VALUE": "PIN" }, "LOCK_TYPE_NONE": { "TYPE": "TEXT", "VALUE": "None" }, "CONTINUE_BUTTON": { "TYPE": "TEXT", "VALUE": "Continue" }, "CONFIRM_BUTTON": { "TYPE": "TEXT", "VALUE": "Confirm" }, "ENTER_PASSWORD": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" }, "PIN_PAD": { "TYPE": "RESOURCE_ID", "VALUE": "pin_pad", "PACKAGE": "com.android.car.settings" }, "ENTER_PIN_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "key_enter", "PACKAGE": "com.android.car.settings" }, "REMOVE_BUTTON": { "TYPE": "TEXT", "VALUE": "Remove" } } }, "PHONE": { "APPLICATION_CONFIG": { "DIAL_PACKAGE": "com.android.car.dialer", "PHONE_ACTIVITY": "com.android.car.dialer/.ui.TelecomActivity", "OPEN_DIAL_PAD_COMMAND": "am start -a android.intent.action.DIAL" }, "IN_CALL_VIEW": { "DIALED_CONTACT_TITLE": { "TYPE": "RESOURCE_ID", "VALUE": "user_profile_title", "PACKAGE": "com.android.car.dialer" }, "DIALED_CONTACT_NUMBER": { "TYPE": "RESOURCE_ID", "VALUE": "user_profile_phone_number", "PACKAGE": "com.android.car.dialer" }, "END_CALL": { "TYPE": "RESOURCE_ID", "VALUE": "end_call_button", "PACKAGE": "com.android.car.dialer" }, "MUTE_CALL": { "TYPE": "RESOURCE_ID", "VALUE": "mute_button", "PACKAGE": "com.android.car.dialer" }, "SWITCH_TO_DIAL_PAD": { "TYPE": "RESOURCE_ID", "VALUE": "toggle_dialpad_button", "PACKAGE": "com.android.car.dialer" }, "CHANGE_VOICE_CHANNEL": { "TYPE": "RESOURCE_ID", "VALUE": "voice_channel_view", "PACKAGE": "com.android.car.dialer" }, "VOICE_CHANNEL_CAR": { "TYPE": "TEXT", "VALUE": "Car speakers" }, "VOICE_CHANNEL_PHONE": { "TYPE": "TEXT", "VALUE": "Phone" } }, "DIAL_PAD_VIEW": { "DIAL_PAD_MENU": { "TYPE": "TEXT", "VALUE": "Dial Pad" }, "DIAL_PAD_FRAGMENT": { "TYPE": "RESOURCE_ID", "VALUE": "dialpad_fragment", "PACKAGE": "com.android.car.dialer" }, "DIALED_NUMBER": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.dialer" }, "MAKE_CALL": { "TYPE": "RESOURCE_ID", "VALUE": "call_button", "PACKAGE": "com.android.car.dialer" }, "DELETE_NUMBER": { "TYPE": "RESOURCE_ID", "VALUE": "delete_button", "PACKAGE": "com.android.car.dialer" } }, "CONTACTS_VIEW": { "CONTACTS_MENU": { "TYPE": "TEXT", "VALUE": "Contacts" }, "CONTACT_INFO": { "TYPE": "RESOURCE_ID", "VALUE": "call_action_id", "PACKAGE": "com.android.car.dialer" }, "CONTACT_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.dialer" }, "CONTACT_DETAIL": { "TYPE": "RESOURCE_ID", "VALUE": "show_contact_detail_id", "PACKAGE": "com.android.car.dialer" }, "ADD_CONTACT_TO_FAVORITE": { "TYPE": "RESOURCE_ID", "VALUE": "contact_details_favorite_button", "PACKAGE": "com.android.car.dialer" }, "SEARCH_CONTACT": { "TYPE": "RESOURCE_ID", "VALUE": "menu_item_search", "PACKAGE": "com.android.car.dialer" }, "CONTACT_SEARCH_BAR": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_search_bar", "PACKAGE": "com.android.car.dialer" }, "SEARCH_RESULT": { "TYPE": "RESOURCE_ID", "VALUE": "contact_name", "PACKAGE": "com.android.car.dialer" }, "CONTACT_SETTINGS": { "TYPE": "RESOURCE_ID", "VALUE": "menu_item_setting", "PACKAGE": "com.android.car.dialer" }, "CONTACT_ORDER": { "TYPE": "TEXT", "VALUE": "Contact order" }, "SORT_BY_FIRST_NAME": { "TYPE": "TEXT", "VALUE": "First name" }, "SORT_BY_LAST_NAME": { "TYPE": "TEXT", "VALUE": "Last Name" }, "CONTACT_TYPE_WORK": { "TYPE": "TEXT", "VALUE": "Work" }, "CONTACT_TYPE_MOBILE": { "TYPE": "TEXT", "VALUE": "Mobile" }, "CONTACT_TYPE_HOME": { "TYPE": "TEXT", "VALUE": "Home" } }, "CALL_HISTORY_VIEW": { "CALL_HISTORY_MENU": { "TYPE": "TEXT", "VALUE": "Recents" }, "CALL_HISTORY_INFO": { "TYPE": "RESOURCE_ID", "VALUE": "call_action_id", "PACKAGE": "com.android.car.dialer" } }, "FAVORITES_VIEW": { "FAVORITES_MENU": { "TYPE": "TEXT", "VALUE": "Favorites" } } }, "NOTIFICATIONS": { "APPLICATION_CONFIG": { "OPEN_NOTIFICATIONS_COMMAND": "service call statusbar 1" }, "EXPANDED_NOTIFICATIONS_SCREEN": { "NOTIFICATION_VIEW": { "TYPE": "RESOURCE_ID", "VALUE": "notification_view", "PACKAGE": "com.android.systemui" }, "CLEAR_ALL_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "clear_all_button", "PACKAGE": "com.android.systemui" }, "STATUS_BAR": { "TYPE": "RESOURCE_ID", "VALUE": "car_top_navigation_bar_container", "PACKAGE": "com.android.systemui" }, "APP_ICON": { "TYPE": "RESOURCE_ID", "VALUE": "app_icon", "PACKAGE": "com.android.systemui" }, "APP_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "header_text", "PACKAGE": "com.android.systemui" }, "NOTIFICATION_TITLE": { "TYPE": "RESOURCE_ID", "VALUE": "notification_body_title", "PACKAGE": "com.android.systemui" }, "NOTIFICATION_BODY": { "TYPE": "RESOURCE_ID", "VALUE": "notification_body_content", "PACKAGE": "com.android.systemui" }, "CARD_VIEW": { "TYPE": "RESOURCE_ID", "VALUE": "card_view", "PACKAGE": "com.android.systemui" } } }, "MEDIA_CENTER": { "APPLICATION_CONFIG": { "MEDIA_CENTER_PACKAGE": "com.android.car.media", "MEDIA_ACTIVITY": "com.android.bluetooth/com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService" }, "MEDIA_CENTER_SCREEN": { "PLAY_PAUSE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "play_pause_stop", "PACKAGE": "com.android.car.media" }, "NEXT_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_next", "PACKAGE": "com.android.car.media" }, "PREVIOUS_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_prev", "PACKAGE": "com.android.car.media" }, "SHUFFLE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "overflow_on", "PACKAGE": "com.android.car.media" }, "PLAY_QUEUE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "play_queue", "PACKAGE": "com.android.car.media" }, "MINIMIZED_MEDIA_CONTROLS": { "TYPE": "RESOURCE_ID", "VALUE": "minimized_playback_controls", "PACKAGE": "com.android.car.media" }, "TRACK_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.media" }, "TRACK_NAME_MINIMIZED_CONTROL": { "TYPE": "RESOURCE_ID", "VALUE": "minimized_control_bar_title", "PACKAGE": "com.android.car.media" }, "BACK_BUTTON": { "TYPE": "DESCRIPTION", "VALUE": "Back" } }, "MEDIA_CENTER_ON_HOME_SCREEN": { "PLAY_PAUSE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "play_pause_stop", "PACKAGE": "com.android.car.carlauncher" }, "NEXT_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_next", "PACKAGE": "com.android.car.carlauncher" }, "PREVIOUS_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_prev", "PACKAGE": "com.android.car.carlauncher" }, "TRACK_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.carlauncher" } } } }
Альтернативные конфигурации устройства
Следующий пример кода показывает пример файла конфигурации JSON, где настройки по умолчанию переопределяются настройками DUT. В этом примере:
Настройки Интернета на эталонных устройствах называются «Сеть и Интернет» , а на тестируемом устройстве — «Подключение ».
Настройки даты и времени доступны в разделе «Настройки» > «Дата и время» для эталонных устройств и в разделе «Настройки» > «Система» > «Дата и время» для тестируемого устройства.
// 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 | Объект, используемый для построения UI Automator `BySelectors`, который выбирает элементы пользовательского интерфейса (подробно описан ниже). |
WORKFLOWS | Последовательности действий, которые выполняют задачи высокого уровня (подробно описаны ниже). |
Элементы пользовательского интерфейса
Каждый элемент пользовательского интерфейса имеет TYPE
, который определяет, что UI Automator будет искать для идентификации элемента (например, идентификатор ресурса, текст и описание) и значения конфигурации, связанные с этим типом. В общем, всякий раз, когда помощник идентифицирует элемент на экране с помощью этой конфигурации, он получает ровно один элемент. Если конфигурации соответствуют несколько элементов, в тесте используется произвольный элемент. Поэтому конфигурация должна (как правило) быть написана достаточно конкретно, чтобы она сужалась до одного элемента в соответствующем контексте.
ТЕКСТ
Это самый простой тип элемента пользовательского интерфейса. Элемент пользовательского интерфейса идентифицируется по тексту и требует точного соответствия.
"CALL_HISTORY_MENU": {
"TYPE": "TEXT",
"VALUE": "Recents"
}
ТЕКСТ_СОДЕРЖИТ
То же, что и 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
, значение которого имеет ту же форму, что и запись элемента UI (см. выше). Эти TYPE:
НАЖИМАТЬ ДЛИТЕЛЬНОЕ_НАЖАТИЕ ЩЕЛКНИТЕ ДЛИННЫЙ_ЩЕЛЧОК CLICK_IF_EXIST | HAS_UI_ELEMENT_IN_FOREGROUND ПРОКРУТИТЕ, ЧТОБЫ НАЙТИ, И ЩЕЛКНИТЕ ПРОКРУТИТЕ_ТО_НАЙТИ_И_ЩЕЛКНИТЕ_ЕСЛИ_СУЩЕСТВУЕТ ПРОВЕСТИ_ЧТОБЫ_НАЙТИ_И_КЛИКНУТЬ ПРОВЕСТИ_ЧТОБЫ_НАЙТИ_И_ЩЕЛКНИТЕ_ЕСЛИ_СУЩЕСТВУЕТ |
Для других ТИПОВ подробности конфигурации следующие:
Объект | Описание |
---|---|
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 кодовая база 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
для теста Automotive .DEVICE-SERIAL : серийный идентификатор DUT. Этот параметр не требуется, если к хосту подключено только одно устройство.
config-file-path
: Необязательный параметр, который требуется только для предоставления нестандартных конфигураций пользовательского интерфейса устройства, как указано в файле конфигурации JSON . Если не указано, фреймворк использует значения по умолчанию для выполнения тестов.PATH-FOR-BUILT-TEST-APK : путь, по которому собирается тестовый APK при выполнении команды
make
.TEST-PACKAGE : Название тестового пакета.
TEST-CLASSNAME : Имя тестового класса. Например, для теста настроек Wifi тестовый пакет —
android.platform.tests
, а имя тестового класса —WifiSettingTest
.
Библиотека фрагментов для автомобильной промышленности
Automotive Snippet Library — это набор библиотек Android Test для Android Open Source Project (AOSP), разработанных для взаимодействия с автомобильными приложениями и сервисами. Он использует Spectatio с удобным механизмом для выполнения удаленных вызовов процедур (RPC) с хостовой (тестовой) машины на устройство под управлением Android.
Начать
Прежде чем начать, просмотрите эти разделы.
Предпосылки
- На хост-компьютере установлен Python 3.x.
- Настройка среды AOSP с необходимыми инструментами сборки.
- Автомобильное устройство Android (эмулятор или физическое устройство) с доступом adb.
Компиляция
Для компиляции различных фрагментов, предоставляемых Automotive Snippet Library, вы можете использовать предоставленный файл 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 devices, если подключено несколько устройств.
Включенные библиотеки
Библиотека сниппетов для автомобильной промышленности включает в себя следующие библиотеки сниппетов и помощников:
AutomotiveSnippet: предоставляет API, связанные с операциями с транспортным средством, такими как набор номера, регулировка громкости, аппаратные клавиши автомобиля и взаимодействие с медиацентром.
PhoneSnippet: предоставляет API, связанные с телефонией, включая обработку вызовов, просмотр контактов и операции с SMS.
Сниппет Automotive и PhoneSnippet имеют некоторую общую логику. В частности, вы можете вторгнуться в вызовы RCP, связанные с Bluetooth, чтобы спарить автомобильное и телефонное устройства. Этот bt_discovery_test
показывает, как это сделать.
- TEST-CLASSNAME : Имя тестового класса. Например, для теста настроек Wifi тестовый пакет —
android.platform.tests
, а имя тестового класса —WifiSettingTest
.