Spectatio é uma estrutura de teste de código aberto desenvolvida para testar o Android Automotive OS (AAOS) em dispositivos reais e virtuais. Spectatio fornece APIs para testar aplicativos em um dispositivo automotivo e é uma solução extensível e escalável usada para verificar a capacidade e o desempenho do AAOS e seus aplicativos.
Design de alto nível
A estrutura Spectatio é adaptável e expansível para várias implementações de UI AAOS. É usado para testar a capacidade e o desempenho do AAOS em hardware de dispositivos, emuladores e ambientes virtualizados.
A figura a seguir explica o design de alto nível da estrutura Spectatio.
Figura 1. Design de alto nível da estrutura Spectatio.
Construída com base no UI Automator , a estrutura Spectatio fornece um conjunto de APIs para construir testes de UI que interagem com aplicativos de usuário e de sistema no AAOS. Os testes automotivos usam as APIs fornecidas pela estrutura Spectatio para testes, o que torna esses testes independentes do dispositivo em teste (DUT) e escalonáveis para testar dispositivos variados, se houver suporte.
A Figura 1 mostra que a estrutura Spectatio é modularizada com base em aplicativos de referência, como Dialer, Medicenter e Settings, usando interfaces e auxiliares específicos do aplicativo, tornando-a facilmente extensível para novos aplicativos. A estrutura Spectatio reutiliza as classes auxiliares padrão e utilitárias comuns. A classe auxiliar padrão é a classe pai para todas as funções auxiliares do aplicativo e fornece funções padrão específicas do dispositivo ou aplicáveis entre aplicativos. As classes auxiliares de utilitário fornecem utilitários como leitura ou gravação de arquivos do dispositivo.
Arquitetura
Para fornecer um conjunto de APIs para construir testes de UI, a estrutura Spectatio implementa interfaces e auxiliares específicos do aplicativo enquanto estende a classe auxiliar padrão existente e importa as classes auxiliares do utilitário.
A Figura 2 ilustra a arquitetura de alto nível da estrutura Spectatio e todas as entidades envolvidas na implementação de APIs para testar um aplicativo.
Figura 2. Arquitetura de alto nível do framework Spectatio.
A interface do auxiliar de aplicativo fornece um modelo para a implementação de um auxiliar de aplicativo. Consiste em várias funções auxiliares necessárias para testar aplicativos. Cada aplicativo possui sua própria interface, como IAutoSettingHelper
e IAutoDialHelper
. Para obter mais informações e uma lista de funções de interface, consulte as funções da interface auxiliar do aplicativo no AOSP.
A classe auxiliar padrão consiste em atributos e funções padrão necessários para a configuração do dispositivo, mas não são específicos de nenhum aplicativo, como pressHome
e scroll
. A classe auxiliar padrão é definida em AbstractAutoStandardAppHelper.java
.
As classes auxiliares de utilitário são usadas pela estrutura. Por exemplo, AutoJsonUtility.java
é uma classe de utilitário que carrega o arquivo de configuração JSON do dispositivo fornecido e atualiza as configurações da estrutura em tempo de execução.
O módulo de implementação do auxiliar de aplicativo é o núcleo da estrutura Spectatio. Ele contém a implementação das funções auxiliares definidas na interface auxiliar do aplicativo, que são necessárias para testar aplicativos em um dispositivo automotivo. Cada aplicativo possui sua própria implementação, como SettingHelperImpl
e DialHelperImpl
, usados pelos testes automotivos para testar os aplicativos. Para obter mais informações e uma lista de implementações, consulte as funções de implementação do auxiliar de aplicativo no AOSP.
Os testes automotivos usam as funções de implementação do auxiliar de aplicativo para testar várias operações relacionadas ao aplicativo. Use a classe HelperAccessor
para obter acesso às funções de implementação do auxiliar de aplicativo.
O código a seguir mostra a configuração, limpeza e execução de um exemplo de teste automotivo.
@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());
}
}
Costumização
A estrutura Spectatio é independente da interface do usuário do dispositivo, portanto, é escalonável para testar dispositivos com interfaces de usuário e hardware variados. Para alcançar essa escalabilidade, o Spectatio usa configurações de dispositivo padrão baseadas no dispositivo de referência. Para oferecer suporte a configurações de dispositivo não padrão, a estrutura usa um arquivo de configuração JSON em tempo de execução para definir as alterações de UI desejadas para o dispositivo. Um arquivo de configuração JSON oferece suporte a elementos de UI como TEXT
, DESCRIPTION
e RESOURCE_ID
, juntamente com configurações path
e deve conter apenas as informações sobre as alterações de UI para o DUT. O restante dos elementos da UI usa os valores de configuração padrão fornecidos na estrutura.
Configurações de dispositivo padrão
O exemplo de arquivo de configuração JSON a seguir mostra as configurações de dispositivos disponíveis e seus valores padrão.
Clique aqui para exibir um exemplo de arquivo de configuração 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" } } } }
Configurações alternativas de dispositivos
O exemplo de código a seguir mostra um exemplo do arquivo de configuração JSON em que as configurações padrão são substituídas pelas configurações no DUT. Neste exemplo:
As configurações da Internet são denominadas Rede e Internet nos dispositivos de referência e Conectividade no DUT.
As configurações de data e hora estão disponíveis em Configurações > Data e hora para dispositivos de referência e em Configurações > Sistema > Data e hora para o 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"
},
....
}
Quando o arquivo de configuração JSON estiver pronto, ele será fornecido em tempo de execução, conforme mostrado no seguinte bloco 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
Neste comando:
DEVICE-SERIAL : ID de série do DUT. Este parâmetro não é necessário se apenas um dispositivo estiver conectado ao host.
PATH-TO-JSON-FILE : Caminho do arquivo JSON na máquina host.
Formato de configuração
Existem cinco objetos de nível superior na configuração, com as seguintes chaves e valores:
Objeto | Descrição |
---|---|
PACKAGES | Um objeto que descreve o pacote principal de vários aplicativos, que é usado para determinar quando esse aplicativo está em primeiro plano. |
ACTIONS | Um objeto que indica tipos de ação e parâmetros para diversas ações. Por exemplo, se deve usar botões ou um gesto para rolar. |
COMMANDS | Um objeto que especifica comandos que executam diversas ações. |
UI_ELEMENTS | Um objeto usado para construir o UI Automator `BySelectors` que seleciona elementos da UI (descritos em detalhes abaixo). |
WORKFLOWS | Sequências de ações que realizam tarefas de alto nível (descritas em detalhes abaixo). |
Elementos da interface do usuário
Cada elemento da UI possui um TYPE
que especifica o que o UI Automator procurará para identificar o elemento (como ID do recurso, texto e descrição) e os valores de configuração associados a esse tipo. Em geral, sempre que um helper identifica um elemento na tela utilizando esta configuração, ele obtém exatamente um elemento. Se vários elementos corresponderem à configuração, um elemento arbitrário será usado no teste. Portanto, a configuração deve (geralmente) ser escrita de forma suficientemente específica para se restringir a um elemento no contexto relevante.
TEXTO
Este é o tipo de elemento de UI mais simples. O elemento da UI é identificado pelo seu texto e requer uma correspondência exata.
"CALL_HISTORY_MENU": {
"TYPE": "TEXT",
"VALUE": "Recents"
}
TEXT_CONTAINS
O mesmo que TEXT
, exceto que o VALUE
especificado só precisa aparecer em algum lugar no texto do elemento a ser correspondido.
"PRIVACY_CALENDAR": {
"TYPE": "TEXT_CONTAINS",
"VALUE": "Calendar"
}
DESCRIÇÃO
Identifique o elemento pelo seu atributo de descrição de conteúdo, exigindo uma correspondência exata.
"APP_GRID_SCROLL_BACKWARD_BUTTON": {
"TYPE": "DESCRIPTION",
"VALUE": "Scroll up"
}
RESOURCE_ID
Identifique o elemento pelo seu ID de recurso, opcionalmente verificando também o componente do pacote desse ID. A chave PACKAGE
é opcional; se omitido, qualquer pacote corresponderá e apenas a parte do ID após :id/
será considerada.
"APP_LIST_SCROLL_ELEMENT": {
"TYPE": "RESOURCE_ID",
"VALUE": "apps_grid",
"PACKAGE": "com.android.car.carlauncher"
}
CLICÁVEL, ROLÁVEL
Identifique o elemento com base no fato de ele ser (ou não) clicável ou rolável. Esses são tipos de elementos muito amplos e geralmente só devem ser usados em MULTIPLE
para ajudar a restringir outro tipo de elemento. A chave FLAG
é opcional e o padrão é true
.
"SAMPLE_ELEMENT": {
"TYPE": "CLICKABLE",
"FLAG": false
}
AULA
Identifique o elemento com base em sua classe.
"SECURITY_SETTINGS_ENTER_PASSWORD": {
"TYPE": "CLASS",
"VALUE": "android.widget.EditText"
}
HAS_ANCESTOR
Identifique o elemento consultando a hierarquia do widget em seus ancestrais. A chave ANCESTOR
contém um objeto que identifica o ancestral. A chave DEPTH
especifica até que ponto a hierarquia deve ser observada. DEPTH
é opcional e tem um valor padrão de 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_ANCESTOR",
"DEPTH": 2,
"ANCESTOR": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
HAS_DESCENDANT
Identifique o elemento observando seus filhos na hierarquia. A chave DESCENDANT
contém um objeto que especifica o filho a ser procurado. A chave DEPTH
especifica até que ponto a hierarquia deve ser observada. DEPTH
é opcional e tem um valor padrão de 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_DESCENDANT",
"DEPTH": 2,
"DESCENDANT": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
MÚLTIPLO
Identifique o elemento com base em múltiplas condições simultâneas, todas as quais devem ser atendidas.
"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"
}
}
]
}
Neste exemplo, a configuração identifica um RelativeLayout
que possui um descendente na profundidade 2
, que possui o texto Permission manager
.
Fluxos de trabalho
Um fluxo de trabalho representa uma sequência de ações usadas para realizar uma tarefa específica, que pode diferir bastante de tipo de dispositivo para tipo de dispositivo e é mais flexível para representar na configuração do que no 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 fluxo de trabalho é um par chave-valor em que a chave é o nome do fluxo de trabalho e o valor é uma matriz de ações a serem executadas. Cada ação possui um NAME
, um TYPE
, (geralmente) um CONFIG
e (às vezes) um SWIPE_CONFIG
ou SCROLL_CONFIG
. Para a maioria dos TYPEs, o CONFIG
é um objeto com uma chave UI_ELEMENT
cujo valor assume a mesma forma que uma entrada de elemento UI (veja acima). Esses TIPOS são:
IMPRENSA LONG_PRESS CLIQUE 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 |
Para os demais TYPEs, os detalhes de configuração são:
Objeto | Descrição |
---|---|
COMMAND | Um objeto com um valor TEXT contendo o comando a ser executado. |
HAS_PACKAGE_IN_FOREGROUND | Um objeto com um valor TEXT contendo o pacote. |
SWIPE | Omita a CONFIG key para uma ação SWIPE . Isso usa apenas SWIPE_CONFIG |
WAIT_MS | Um objeto com um valor TEXT contendo o número de milissegundos de espera. |
As ações relacionadas à rolagem e ao deslizar exigem configuração adicional, como segue:
SCROLL_CONFIG
Objeto | Descrição |
---|---|
SCROLL_ACTION | USE_GESTURE ou USE_BUTTON |
SCROLL_DIRECTION | HORIZONTAL ou VERTICAL |
SCROLL_ELEMENT | Um objeto que indica o contêiner a ser rolado, usando o mesmo formato de uma configuração de elemento de UI (veja acima). |
SCROLL_FORWARD , SCROLL_BACKWARD | Os botões de rolagem para frente e para trás (obrigatórios quando SCROLL_ACTION é USE_BUTTON ). |
SCROLL_MARGIN | Se SCROLL_ACTION for USE_GESTURE , a distância da borda do contêiner para iniciar e parar o arrasto que será usado para realizar a rolagem ( Opcional, padrão = 10). |
SCROLL_WAIT_TIME | Se SCROLL_ACTION for USE_GESTURE , o tempo em milissegundos de espera entre os gestos de rolagem ao procurar um objeto para clicar. ( Opcional, padrão = 1). |
SWIPE_CONFIG
Objeto | Descrição |
---|---|
SWIPE_DIRECTION | Ou TOP_TO_BOTTOM , BOTTOM_TO_TOP , LEFT_TO_RIGHT ou RIGHT_TO_LEFT |
SWIPE_FRACTION | Um dos seguintes:
|
NUMBER_OF_STEPS | O número de etapas a serem usadas para realizar o deslizamento. Consulte segmentSteps . |
Construir e executar
A estrutura Spectatio é criada automaticamente como parte do APK de teste. Para criar o APK de teste, a base de código AOSP deve residir na estação de trabalho local. Após a construção do APK de teste, o usuário deve instalar o APK no dispositivo e executar o teste.
O exemplo de código a seguir mostra a criação, instalação e execução de um APK de teste.
# 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
Nestes comandos:
TEST-APK-NAME : O nome do aplicativo a ser testado. Por exemplo, defina TEST-APK-NAME como
AndroidAutomotiveSettingsTests
para testar as configurações de Wi-Fi conforme especificado no arquivoAndroid.bp
. O nome do APK pode ser encontrado no respectivo arquivoAndroid.bp
do teste automotivo .DEVICE-SERIAL : O ID serial do DUT. Este parâmetro não é necessário se apenas um dispositivo estiver conectado ao host.
config-file-path
: parâmetro opcional necessário apenas para fornecer configurações de UI de dispositivo não padrão, conforme especificado no arquivo de configuração JSON . Se não for fornecido, a estrutura utiliza valores padrão para executar os testes.PATH-FOR-BUILT-TEST-APK : o caminho onde o APK de teste é construído quando o comando
make
é executado.TEST-PACKAGE : O nome do pacote de teste.
TEST-CLASSNAME : O nome da classe de teste. Por exemplo, para o teste Wifi Settings , o pacote de teste é
android.platform.tests
e o nome da classe de teste éWifiSettingTest
.
Biblioteca de trechos automotivos
A Automotive Snippet Library é um conjunto de bibliotecas de teste do Android para o Android Open Source Project (AOSP) projetadas para interagir com aplicativos e serviços automotivos. Ele aproveita o Spectatio com um mecanismo conveniente para executar chamadas de procedimento remoto (RPCs) de uma máquina host (teste) para um dispositivo com Android.
iniciar
Antes de começar, revise estas seções.
Pré-requisitos
- Python 3.x instalado na máquina host.
- Configuração do ambiente AOSP com as ferramentas de construção necessárias.
- Um dispositivo automotivo Android (emulador ou dispositivo físico) com acesso adb.
Compilação
Para compilar os vários snippets fornecidos pela Automotive Snippet Library, você pode usar o arquivo android.bp
fornecido. Seguindo os comandos da seção anterior para compilar o APK.
Implantação
Depois de compilar com êxito as bibliotecas de snippets, implante os APKs resultantes no dispositivo de destino usando o comando adb install
mencionado na seção anterior.
Execute testes
As bibliotecas de snippets expõem vários métodos RPC para interagir com o sistema automotivo. Esses métodos podem ser invocados por meio da estrutura Mobly na máquina host. Supondo que você tenha o ambiente de teste Mobly configurado, você pode usar o script snippet_shell.py
para abrir um shell Python interativo, onde você pode invocar manualmente métodos RPC no dispositivo. Exemplo de invocação:
python3 snippet_shell.py com.google.android.mobly.snippet.bundled -s <serial>
Substitua <serial>
pelo número de série do dispositivo, que você pode obter com dispositivos adb se vários dispositivos estiverem conectados.
Bibliotecas incluídas
A Automotive Snippet Library inclui as seguintes bibliotecas de snippets e auxiliares:
AutomotiveSnippet: fornece APIs relacionadas às operações do veículo, como discagem, controle de volume, teclas físicas do veículo e interação na central de mídia.
PhoneSnippet: fornece APIs relacionadas à telefonia, incluindo tratamento de chamadas, navegação de contatos e operações de SMS.
O snippet Automotive e o PhoneSnippet compartilham alguma lógica comum. Especificamente, você pode invadir chamadas RCP relacionadas ao Bluetooth para emparelhar um dispositivo automotivo e um dispositivo telefônico. Este bt_discovery_test
mostra como.
- TEST-CLASSNAME : O nome da classe de teste. Por exemplo, para o teste Wifi Settings , o pacote de teste é
android.platform.tests
e o nome da classe de teste éWifiSettingTest
.