Spectatio es un framework de prueba de código abierto desarrollado para probar Android Automotive OS (AAOS) en dispositivos reales y virtuales Spectatio proporciona APIs para pruebas de apps en un dispositivo de la industria automotriz y es una solución extensible y escalable que se utiliza para verificar la capacidad y el rendimiento de AAOS y sus aplicaciones.
Diseño de alto nivel
El framework Spectatio es adaptable y expandible para varias IU de AAOS. de Google Cloud. Se usa para probar la capacidad y el rendimiento de AAOS en hardware del dispositivo, emuladores y entornos virtualizados.
En la siguiente figura, se explica el diseño de alto nivel del framework Spectatio.
Figura 1: Diseño de alto nivel del framework de Spectatio.
El framework de Spectatio se basa en UI Automator y proporciona un conjunto de APIs. para compilar pruebas de IU que interactúen con apps de usuarios y sistemas en AAOS. Automotriz las pruebas usan las APIs proporcionadas por el framework Spectatio para realizar pruebas, lo que facilita estas pruebas independientemente del dispositivo que se está probando (DUT) y escalables para probar diversos dispositivos, si son compatibles.
En la Figura 1, se muestra que el framework de Spectatio está modularizado según las referencias apps como Teléfono, Medicenter y Configuración usando apps específicas interfaces de usuario y asistentes, lo que facilita su adaptación a apps nuevas. El espectáculo reutilice las clases auxiliares estándar y de utilidad comunes. La clase auxiliar estándar es la clase superior de todas las funciones auxiliares de la app y proporciona funciones estándar que son específicas del dispositivo o aplicables a todas las apps. El las clases de ayuda de utilidades ofrecen utilidades como leer o escribir archivos desde el dispositivo.
Arquitectura
A fin de proporcionar un conjunto de APIs para compilar pruebas de IU, el framework de Spectatio implementa interfaces y asistentes específicos de la app, a la vez que amplías el asistente estándar existente e importar las clases auxiliares de utilidad.
En la Figura 2, se ilustra la arquitectura de alto nivel del framework de Spectatio. todas las entidades involucradas en la implementación de APIs para probar una app.
Figura 2: Arquitectura de alto nivel del framework de Spectatio.
La interfaz de ayuda de la app proporciona un modelo para la implementación de
un asistente de aplicaciones. Consta de varias funciones auxiliares necesarias
para probar apps. Cada app tiene su propia interfaz, como IAutoSettingHelper
.
y IAutoDialHelper
.
Para obtener más información y una lista de funciones de la interfaz, consulta las funciones de interfaz auxiliares de la app en AOSP.
La clase auxiliar estándar consta de atributos y funciones estándares que se
se requieren para la configuración del dispositivo, pero no son específicos para ninguna app, como pressHome
y scroll
. La clase auxiliar estándar se define en AbstractAutoStandardAppHelper.java
.
El framework usa las clases auxiliares de utilidad. Para
Por ejemplo, AutoJsonUtility.java
es un
clase de utilidad que carga el archivo de configuración JSON del dispositivo determinado y las actualizaciones
los parámetros de configuración del framework en el entorno de ejecución.
El módulo de implementación auxiliar de la app es el núcleo de Spectatio
en un framework de aplicaciones. Contiene la implementación de las funciones auxiliares definidas en
la interfaz de ayuda de la app, que se requieren para probar apps en un
de un dispositivo de automóviles. Cada app tiene su propia implementación, como SettingHelperImpl
.
y
DialHelperImpl
:
utilizado por
las pruebas de Automotive para probar las apps. Para obtener más información y una lista de
consulta las funciones de implementación auxiliares de la app
en AOSP.
Pruebas de vehículos
Usar las funciones de implementación auxiliares de la app para probar varias operaciones
relacionadas con la app. Usa la clase HelperAccessor
para obtener acceso a las funciones de implementación auxiliares de la app.
En el siguiente código, se muestran la configuración, la limpieza y la ejecución de una muestra para pruebas de automóviles.
@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());
}
}
Personalización
El framework de Spectatio es independiente de la IU del dispositivo, por lo que es escalable para
dispositivos de prueba con diversas IUs y hardware. Para lograr esta escalabilidad,
Spectatio usa configuraciones de dispositivos predeterminadas según el dispositivo de referencia. Para
admiten configuraciones de dispositivos no predeterminadas, el framework usa un archivo
en el entorno de ejecución para establecer los cambios deseados en la IU del dispositivo. R
El archivo de configuración JSON admite elementos de la IU como TEXT
, DESCRIPTION
y
RESOURCE_ID
, junto con la configuración de path
, y debe contener solo la información
sobre los cambios en la IU del DUT. El resto de los elementos de la IU usan la configuración
de configuración proporcionados en el framework.
Parámetros de configuración predeterminados de los dispositivos
En el siguiente ejemplo de archivo de configuración JSON, se muestra el dispositivo disponible parámetros de configuración y sus valores predeterminados.
Haz clic aquí para mostrar un JSON de muestra archivo de configuración
{ "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" } } } }
Configuraciones alternativas de dispositivos
En la siguiente muestra de código, se muestra un ejemplo del archivo de configuración JSON en el que la configuración predeterminada se anula con la del DUT. En este ejemplo:
La configuración de Internet se denomina Red & Internet en dispositivos de referencia y Conectividad en el DUT.
La configuración de fecha y hora está disponible en Configuración > Fecha y hora de dispositivos de referencia y en Configuración > Sistema > Fecha y hora del 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"
},
....
}
Cuando el archivo de configuración JSON está listo, se proporciona en el entorno de ejecución, como se muestra en el siguiente bloque de código:
# Push The JSON configuration file to the device
adb -s DEVICE-SERIAL push PATH-OF-JSON-FILE /data/local/tmp/runtimeSpectatioConfig.json
En este comando:
DEVICE-SERIAL: Es el ID de serie del DUT. Este parámetro no es se requiere si solo hay un dispositivo conectado al host.
PATH-TO-JSON-FILE: Es la ruta de acceso al archivo JSON en la máquina anfitrión.
Formato de configuración
Hay cinco objetos de nivel superior en la configuración, con las siguientes claves y sus valores:
Objeto | Descripción |
---|---|
PACKAGES |
Un objeto que describe el paquete principal de varias apps, que se usa para determinar cuándo la app está en primer plano. |
ACTIONS |
Un objeto que indica tipos de acciones y parámetros para varias acciones. Por ejemplo, si se deben usar botones o un gesto para desplazarse. |
COMMANDS |
Un objeto que especifica comandos que realizan varias acciones. |
UI_ELEMENTS |
Un objeto que se usa para construir "BySelectors" de UI Automator que seleccionan IU Elementos (que se describen en detalle a continuación). |
WORKFLOWS |
Secuencias de acciones que realizan tareas de alto nivel (descritas en a continuación). |
Elementos de la IU
Cada elemento de la IU tiene un TYPE
que especifica lo que UI Automator buscará para
identificar el elemento (como el ID del recurso, el texto y la descripción)
de configuración asociados con ese tipo. En general, siempre que un asistente
identifica un elemento en la pantalla mediante esta configuración, obtiene
un elemento. Si varios elementos coinciden con la configuración, se asigna uno arbitrario
que se usó en la prueba. Por lo tanto, la configuración (generalmente) se debe escribir
lo suficientemente específico como para que se limite a un elemento en el contexto relevante.
TEXTO
Este es el tipo de elemento de IU más simple. El elemento de la IU se identifica por su texto, y requiere una concordancia exacta.
"CALL_HISTORY_MENU": {
"TYPE": "TEXT",
"VALUE": "Recents"
}
TEXT_CONTIENE
Es igual que TEXT
, con la excepción de que el VALUE
especificado solo debe aparecer en algún lugar de
el texto del elemento con el que se buscarán coincidencias.
"PRIVACY_CALENDAR": {
"TYPE": "TEXT_CONTAINS",
"VALUE": "Calendar"
}
DESCRIPCIÓN
Identificar el elemento por su atributo de descripción de contenido, y se requiere una indicación la coincidencia.
"APP_GRID_SCROLL_BACKWARD_BUTTON": {
"TYPE": "DESCRIPTION",
"VALUE": "Scroll up"
}
ID_RECURSO
Identifica el elemento por su ID de recurso y, opcionalmente, también puedes verificar el paquete
de ese ID. La clave PACKAGE
es opcional. si se omite, cualquier paquete
coincidirá y solo se considerará la parte del ID posterior a :id/
.
"APP_LIST_SCROLL_ELEMENT": {
"TYPE": "RESOURCE_ID",
"VALUE": "apps_grid",
"PACKAGE": "com.android.car.carlauncher"
}
SE PUEDE HACER CLIC Y DESACTIVAR
Identifica el elemento según si se puede hacer clic (o no) o si se puede desplazar.
Estos son tipos de elementos muy amplios y, por lo general, solo deben usarse en un
MULTIPLE
para ayudar a acotar otro tipo de elemento. La clave FLAG
es opcional.
y la configuración predeterminada es true
.
"SAMPLE_ELEMENT": {
"TYPE": "CLICKABLE",
"FLAG": false
}
CLASE
Identifica el elemento según su clase.
"SECURITY_SETTINGS_ENTER_PASSWORD": {
"TYPE": "CLASS",
"VALUE": "android.widget.EditText"
}
HAS_ANCESTOR
Identifica el elemento buscando la jerarquía de widgets en sus principales. El
La clave ANCESTOR
contiene un objeto que identifica al principal. La tecla DEPTH
especifica cuán arriba en la jerarquía se debe ver. DEPTH
es opcional y tiene un
valor predeterminado de 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_ANCESTOR",
"DEPTH": 2,
"ANCESTOR": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
HAS_DESCENDANT
Identifica el elemento mirando hacia abajo en la jerarquía, en sus elementos secundarios. El
La clave DESCENDANT
contiene un objeto que especifica el elemento secundario que se debe buscar. El
La clave DEPTH
especifica qué tan arriba en la jerarquía debe verse. DEPTH
es opcional y
tiene un valor predeterminado de 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_DESCENDANT",
"DEPTH": 2,
"DESCENDANT": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
VARIOS
Identificar el elemento en función de múltiples condiciones simultáneas, las cuales se deben cumplir.
"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"
}
}
]
}
En este ejemplo, la configuración identifica un RelativeLayout
que tiene un
subordinado con 2
de profundidad, que tiene el texto Permission manager
.
Workflows
Un flujo de trabajo representa una secuencia de acciones utilizadas para lograr un tarea, que puede diferir lo suficiente de un tipo de dispositivo a otro y es más más flexibles para representar en la configuración que en el código.
"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"
}
}
}
]
}
Cada flujo de trabajo es un par clave-valor en el que la clave es el nombre del flujo de trabajo y
el valor es un array de acciones para realizar. Cada acción tiene un NAME
, un TYPE
,
(por lo general) un CONFIG
y (a veces) un SWIPE_CONFIG
o SCROLL_CONFIG
. Para
la mayoría de los TYPEs, el CONFIG
es un objeto con una clave UI_ELEMENT
cuyo valor toma
de la misma forma que una entrada de elemento de la IU (ver arriba). Estos TYPE son:
PRESS LONG_PRESS CLIC LONG_CLIC CLIC_IF_EXIST |
HAS_UI_ELEMENT_IN_FOREGROUND DESPLAZAMIENTO_PARA_ENCONTRAR_Y_CLIC SCROLL_TO_FIND_AND_CLIC_IF_EXIST SWIPE_TO_FIND_AND_CLIC SWIPE_TO_FIND_AND_CLIC_IF_EXISTE |
Para los otros TIPOS, los detalles de configuración son:
Objeto | Descripción |
---|---|
COMMAND |
Un objeto con un valor TEXT que contiene el comando que se ejecutará. |
HAS_PACKAGE_IN_FOREGROUND |
Un objeto con un valor TEXT que contiene el paquete. |
SWIPE |
Omite CONFIG key para una acción SWIPE . Esta
solo usa SWIPE_CONFIG |
WAIT_MS |
Un objeto con un valor TEXT que contiene la cantidad de
milisegundos que esperar. |
Las acciones relacionadas con el desplazamiento y el deslizamiento requieren una configuración adicional, como se indica a continuación:
DESPLAZAMIENTO_CONFIGURACIÓN
Objeto | Descripción |
---|---|
SCROLL_ACTION |
USE_GESTURE o USE_BUTTON |
SCROLL_DIRECTION |
HORIZONTAL o VERTICAL |
SCROLL_ELEMENT |
Un objeto que indica el contenedor que se debe desplazar, con el mismo formato que una IU Configuración del elemento (ver arriba). |
SCROLL_FORWARD , SCROLL_BACKWARD |
Los botones de desplazamiento hacia adelante y hacia atrás (necesarios cuando
SCROLL_ACTION es USE_BUTTON ). |
SCROLL_MARGIN |
Si SCROLL_ACTION es USE_GESTURE , la distancia
desde el borde del contenedor para iniciar y detener el arrastre que se usará
para realizar el desplazamiento (opcional, predeterminado = 10). |
SCROLL_WAIT_TIME |
Si SCROLL_ACTION es USE_GESTURE , la hora en
milisegundos para esperar entre los gestos de desplazamiento cuando se busca un objeto y
o hacer clic.
(Opcional, valor predeterminado = 1). |
SWIPE_CONFIGURA
Objeto | Descripción |
---|---|
SWIPE_DIRECTION |
TOP_TO_BOTTOM , BOTTOM_TO_TOP ,
LEFT_TO_RIGHT o RIGHT_TO_LEFT |
SWIPE_FRACTION |
Una de las siguientes opciones:
|
NUMBER_OF_STEPS |
La cantidad de pasos que se deben seguir para realizar el deslizamiento. Consulta los
segmentSteps .
|
Compila y ejecuta
El framework de Spectatio se compila automáticamente como parte del APK de prueba. Para compilar el APK de prueba, la base de código AOSP debe residir en la estación de trabajo local. Después del de prueba se compila el APK de prueba, el usuario debe instalarlo en el dispositivo y ejecutar la la prueba.
En el siguiente ejemplo de código, se muestra la compilación, la instalación y la ejecución de un APK de prueba.
# 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
En estos comandos:
TEST-APK-NAME: Es el nombre de la app que se probará. Por ejemplo, establece TEST-APK-NAME a
AndroidAutomotiveSettingsTests
para probar la configuración de Wi-Fi como se especifica enAndroid.bp
. El nombre del APK se puede encontrar en el archivoAndroid.bp
respectivo de la prueba de Automotive.DEVICE-SERIAL: Es el ID de serie del DUT. Este parámetro no es se requiere si solo hay un dispositivo conectado al host.
config-file-path
: Parámetro opcional que solo se requiere para proporcionar parámetros de configuración de la IU del dispositivo no predeterminados, como se especifica en la sección de configuración de JSON archivo. Si no se proporciona, el usa valores predeterminados para ejecutar las pruebas.PATH-FOR-BUILT-TEST-APK: Es la ruta de acceso en la que se compila el APK de prueba. Cuando se ejecuta el comando
make
.TEST-PACKAGE: Es el nombre del paquete de prueba.
TEST-CLASSNAME: Es el nombre de la clase de prueba. Por ejemplo, para la Wi-Fi Settings, el paquete de prueba es
android.platform.tests
y el el nombre de la clase de prueba esWifiSettingTest
.
Biblioteca de fragmentos de Automotive
La Biblioteca de fragmentos de Automotive es un conjunto de bibliotecas de Android Test para el Proyecto de código abierto de Android (AOSP) diseñado para interactuar con la industria automotriz y servicios de Google. Aprovecha Spectatio con un mecanismo conveniente para ejecutar llamadas de procedimiento remoto (RPC) desde una máquina host (de prueba) a un Dispositivo con Android.
Comenzar
Antes de comenzar, revisa estas secciones.
Requisitos previos
- Python 3.x instalado en la máquina anfitrión.
- Configuración del entorno de AOSP con las herramientas de compilación necesarias.
- Un dispositivo Android Automotive (emulador o dispositivo físico) con acceso a adb
Compilación
Para compilar los distintos fragmentos que proporciona la Biblioteca de fragmentos de Automotive, puedes hacer lo siguiente:
puedes usar el archivo android.bp
proporcionado. Si sigues los comandos en la clase anterior
para compilar el APK.
Implementación
Luego de compilar correctamente las bibliotecas de fragmentos, implementa los APK resultantes en
el dispositivo de destino con el comando adb install
que se mencionó antes
sección.
Cómo ejecutar pruebas
Las bibliotecas de fragmentos exponen varios métodos de RPC para interactuar con la industria automotriz
en un sistema de archivos. Estos métodos pueden invocarse mediante el framework de Mobly desde el host
máquina. Suponiendo que tienes configurado el entorno de pruebas de Mobly, puedes utilizar el
Secuencia de comandos snippet_shell.py
para abrir una shell interactiva de Python, en la que puedes
invocar manualmente métodos de RPC en el dispositivo. Ejemplo de invocación:
python3 snippet_shell.py com.google.android.mobly.snippet.bundled -s <serial>
Reemplaza <serial>
por el número de serie del dispositivo, que puedes obtener con
Dispositivos adb si hay varios dispositivos conectados.
Bibliotecas incluidas
La Biblioteca de fragmentos de Automotive incluye las siguientes bibliotecas de fragmentos y auxiliares:
AutomotiveFragment: Proporciona APIs relacionadas con las operaciones de vehículos, como las siguientes: marcado, control de volumen, teclas físicas del vehículo e interacción con el centro multimedia.
PhoneFragment: Proporciona APIs relacionadas con la telefonía, incluidos el manejo de llamadas, navegación de contactos y operaciones de SMS.
El fragmento de Automotive y el Phonesnippet comparten una lógica en común.
Específicamente, puedes invadir las llamadas de RCP relacionadas con Bluetooth para vincular un automóvil
y un teléfono. En bt_discovery_test
, se muestra cómo hacerlo.
- TEST-CLASSNAME: Es el nombre de la clase de prueba. Por ejemplo, para la
Prueba Configuración de Wi-Fi.
el paquete de prueba es
android.platform.tests
y el nombre de la clase de prueba esWifiSettingTest
.