O Spectatio é um framework de testes de código aberto desenvolvido para testar Automotive OS (AAOS) em dispositivos reais e virtuais. A Spectatio fornece APIs para de testes de apps em um dispositivo automotivo e é uma solução extensível e escalonável usada para verificar a capacidade e o desempenho do AAOS e dos apps dele.
Design de alto nível
O framework Spectatio é adaptável e expansível para várias interfaces do AAOS e implementações. Ele é 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 do Spectatio.
Figura 1. Design de alto nível da estrutura Spectatio.
Criado com base no UI Automator, o framework Spectatio fornece um conjunto de APIs para criar testes de IU que interagem com apps do sistema e do usuário no AAOS. Automóveis usam as APIs fornecidas pela estrutura Spectatio para testes, o que facilita esses testes independentes do dispositivo em teste (DUT, na sigla em inglês) e escalonáveis para testar. de vários dispositivos, se compatíveis.
A Figura 1 mostra que o framework Spectatio é modularizado com base na referência como Telefone, Medicenter e Configurações, usando aplicativos específicos e auxiliares, tornando-o facilmente extensível para novos apps. The Spectatio reutiliza as classes auxiliares padrão e utilitários comuns. A classe auxiliar padrão é a classe pai para todas as funções auxiliares do app e fornece funções padrão específicas do dispositivo ou aplicáveis a vários apps. A As classes auxiliares de utilitário oferecem utilitários como ler ou gravar arquivos do dispositivo.
Arquitetura
Para fornecer um conjunto de APIs para criar testes de interface, o framework Spectatio implementa interfaces e assistentes específicos do app, ampliando o assistente padrão existente e importando as classes auxiliares de 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 auxiliar do aplicativo fornece um modelo para a implementação de
um assistente de app. Ele consiste em várias funções auxiliares que são necessárias
para testar apps. Cada app tem a própria interface, como IAutoSettingHelper
.
e IAutoDialHelper
.
Para mais informações e uma lista de funções de interface, consulte as funções da interface auxiliar do app no AOSP.
A classe auxiliar padrão consiste em atributos e funções padrão que são
necessários para a configuração do dispositivo, mas não são específicos para nenhum app, como pressHome
e scroll
. A classe auxiliar padrão é definida em AbstractAutoStandardAppHelper.java
.
As classes auxiliares de utilitário são usadas pelo framework. Para
exemplo, AutoJsonUtility.java
é uma
classe de utilitário que carrega determinado arquivo de configuração JSON do dispositivo e as atualiza
as configurações do framework no ambiente de execução.
O módulo de implementação do assistente de apps é o núcleo do Spectatio.
de análise de dados em nuvem. Ele contém a implementação das funções auxiliares definidas em
interface auxiliar do app, que são necessárias para testar apps em uma
um dispositivo automotivo. Cada app tem a própria implementação, como SettingHelperImpl
.
e
DialHelperImpl
,
usado por
os testes do Automotive para testar os apps. Para mais informações e uma lista de
implementações, consulte as funções de implementação do assistente de app
no AOSP.
Testes automotivos
usar as funções de implementação auxiliares do app para testar várias operações
relacionadas ao app. Usar a classe HelperAccessor
para ter acesso às funções de implementação auxiliar do app.
O código a seguir mostra a configuração, a limpeza e a execução de um exemplo para testes automotivos.
@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());
}
}
Personalização
O framework Spectatio é independente da interface do dispositivo, portanto, é escalonável para
de testes de dispositivos com interfaces e hardware variados. Para alcançar essa escalonabilidade,
O Spectatio usa as configurações de dispositivo padrão com base no dispositivo de referência. Para
oferecem suporte a configurações de dispositivos não padrão, o framework usa um
arquivo de configuração no tempo de execução para definir as mudanças de interface desejadas para o dispositivo. Um
O arquivo de configuração JSON oferece suporte a elementos da interface como TEXT
, DESCRIPTION
e
RESOURCE_ID
, junto com as configurações de path
, e precisa conter apenas as informações
sobre as mudanças na interface do DUT. O restante dos elementos da interface usa o padrão
valores de configuração fornecidos no framework.
Configurações padrão do dispositivo
O exemplo de arquivo de configuração JSON abaixo mostra o dispositivo disponível e os valores padrão delas.
Clique aqui para exibir um exemplo de JSON arquivo de configuração
{ "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 do dispositivo
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 de Internet são chamadas de Rede e Internet em 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 de dispositivos de referência e em Configurações > Sistema > Data e hora do 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 no ambiente de execução, conforme mostrado em este 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
Nesse comando:
DEVICE-SERIAL: o 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 da configuração
Há 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 são usados para determinar quando esse app está em primeiro plano. |
ACTIONS |
Um objeto que indica os tipos de ação e os parâmetros para várias ações. Por exemplo, se é preciso usar botões ou um gesto para rolar. |
COMMANDS |
Um objeto que especifica comandos que executam várias ações. |
UI_ELEMENTS |
Objeto usado para construir "BySelectors" do UI Automator, que seleciona a interface. Elementos (descritos em detalhes abaixo). |
WORKFLOWS |
Sequências de ações que realizam tarefas de alto nível (descritas em detalhes abaixo). |
Elementos da interface
Cada elemento da interface tem um TYPE
que especifica o que o UI Automator vai procurar
identificar o elemento (como ID do recurso, texto e descrição) e
valores de configuração associados a esse tipo. Em geral, sempre que um assistente
um elemento na tela usando essa configuração, ele recebe exatamente
um elemento. Se vários elementos corresponderem à configuração, um deles será arbitrário,
usados no teste. Portanto, a configuração deve (geralmente) ser escrita
especificamente o suficiente para se limitar a um elemento no contexto relevante.
TEXT
Esse é o tipo de elemento de interface mais simples. O elemento da interface é identificado pelo texto, e requer uma correspondência exata.
"CALL_HISTORY_MENU": {
"TYPE": "TEXT",
"VALUE": "Recents"
}
TEXT_CONTÉM
Igual a TEXT
, exceto pelo fato de que o VALUE
especificado só precisa aparecer em algum lugar nos
o texto do elemento a ser correspondido.
"PRIVACY_CALENDAR": {
"TYPE": "TEXT_CONTAINS",
"VALUE": "Calendar"
}
DESCRIÇÃO
Identifique o elemento pelo atributo descrição do conteúdo, exigindo uma resposta são correspondentes.
"APP_GRID_SCROLL_BACKWARD_BUTTON": {
"TYPE": "DESCRIPTION",
"VALUE": "Scroll up"
}
ID DO RECURSO
Identifique o elemento pelo ID do recurso, verificando também o pacote
desse ID. A chave PACKAGE
é opcional. se omitido, qualquer pacote
vão coincidir, e apenas a parte do ID depois de :id/
será considerada.
"APP_LIST_SCROLL_ELEMENT": {
"TYPE": "RESOURCE_ID",
"VALUE": "apps_grid",
"PACKAGE": "com.android.car.carlauncher"
}
CLICÁVEL, RASCULÁVEL
Identifique o elemento com base no fato de ele ser (ou não) clicável ou rolável.
São tipos de elementos muito amplos e geralmente só devem ser usados em um
MULTIPLE
para ajudar a restringir outro tipo de elemento. A chave FLAG
é opcional,
e o padrão é true
.
"SAMPLE_ELEMENT": {
"TYPE": "CLICKABLE",
"FLAG": false
}
CLASSE
Identifique o elemento com base na classe dele.
"SECURITY_SETTINGS_ENTER_PASSWORD": {
"TYPE": "CLASS",
"VALUE": "android.widget.EditText"
}
TEM_ANCESTOR
Identifique o elemento pesquisando a hierarquia de widgets nos ancestrais dele. A
A chave ANCESTOR
contém um objeto que identifica o ancestral. A chave DEPTH
especifica o nível de hierarquia a ser visto. DEPTH
é opcional e tem
o valor padrão de 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_ANCESTOR",
"DEPTH": 2,
"ANCESTOR": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
HAS_DESCENDANT
Identifique o elemento olhando para baixo na hierarquia para seus filhos. A
A chave DESCENDANT
contém um objeto que especifica o filho a ser buscado. A
A tecla DEPTH
especifica o nível de detalhamento na hierarquia. DEPTH
é opcional e
tem um valor padrão de 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_DESCENDANT",
"DEPTH": 2,
"DESCENDANT": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
VÁRIOS
Identifique o elemento com base em várias condições simultâneas, todas elas precisam ser cumpridas.
"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 tem um
descendente na profundidade 2
, que tem o texto Permission manager
.
Workflows
Um fluxo de trabalho representa uma sequência de ações usadas para realizar uma determinada tarefa, que pode diferir o suficiente de um tipo de dispositivo para o de dispositivo e é mais flexíveis para representar na configuração e não 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 de 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 tem um NAME
, um TYPE
(geralmente) um CONFIG
e, às vezes, um SWIPE_CONFIG
ou SCROLL_CONFIG
. Para
na maioria dos TIPOS, o CONFIG
é um objeto com uma chave UI_ELEMENT
, cujo valor toma
do mesmo formato de uma entrada de elemento da interface do usuário (veja acima). Esses TYPE são:
PRESSIONE 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 DESLIZAR_TO_FIND_AND_CLICK_IF_EXIST |
Para os outros TIPOS, os detalhes de configuração são:
Objeto | Descrição |
---|---|
COMMAND |
Um objeto com um valor TEXT que contém o comando a ser executado. |
HAS_PACKAGE_IN_FOREGROUND |
Um objeto com um valor TEXT que contém o pacote. |
SWIPE |
Omita o CONFIG key para uma ação SWIPE . Isso
usa apenas SWIPE_CONFIG |
WAIT_MS |
Um objeto com um valor TEXT que contém o número de
milésimos de segundo para esperar. |
As ações relacionadas a rolagem e deslize exigem configuração adicional, da seguinte maneira:
SCROLL_CONFIG
Objeto | Descrição |
---|---|
SCROLL_ACTION |
USE_GESTURE ou USE_BUTTON |
SCROLL_DIRECTION |
HORIZONTAL ou VERTICAL |
SCROLL_ELEMENT |
Objeto que indica o contêiner para rolagem, usando a mesma forma de uma interface. Configuração do elemento (veja acima). |
SCROLL_FORWARD , SCROLL_BACKWARD |
Os botões de rolagem para frente e para trás (obrigatórios ao
SCROLL_ACTION é USE_BUTTON ). |
SCROLL_MARGIN |
Se SCROLL_ACTION for USE_GESTURE , a distância
da borda do contêiner para iniciar e interromper a ação de arrastar que será usada
para fazer a rolagem (Opcional,padrão = 10). |
SCROLL_WAIT_TIME |
Se SCROLL_ACTION for USE_GESTURE , o horário em
de milésimos de segundo para esperar entre os gestos de rolagem ao pesquisar um objeto para
clicar.
(Opcional, padrão = 1). |
DESLIZAR_CONFIGURAÇÃO
Objeto | Descrição |
---|---|
SWIPE_DIRECTION |
TOP_TO_BOTTOM , BOTTOM_TO_TOP
LEFT_TO_RIGHT ou RIGHT_TO_LEFT |
SWIPE_FRACTION |
Uma das seguintes:
|
NUMBER_OF_STEPS |
O número de etapas a serem usadas para deslizar. Consulte
segmentSteps .
|
Criar e executar
O framework Spectatio é criado automaticamente como parte do APK de teste. Para criar o APK de teste, a base de código do AOSP precisa residir na estação de trabalho local. Após o é criado, o usuário deve instalá-lo no dispositivo e executar o teste.
O exemplo de código a seguir mostra a criação, a instalação e a 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
Nesses comandos:
TEST-APK-NAME: o nome do app a ser testado. Por exemplo, defina Use o dispositivo TEST-APK-NAME para
AndroidAutomotiveSettingsTests
para testar as configurações de Wi-Fi. conforme especificado emAndroid.bp
. O nome do APK pode ser encontrado no respectivo arquivoAndroid.bp
do o teste automotivo.DEVICE-SERIAL: o ID de série do DUT. Esse parâmetro não está necessário se apenas um dispositivo estiver conectado ao host.
config-file-path
: parâmetro opcional necessário apenas para fornecer configurações de interface de usuário de dispositivo não padrão, conforme especificado na configuração de JSON arquivo. Se não forem fornecidos, os usa valores padrão para executar os testes.PATH-FOR-BUILT-TEST-APK: o caminho em que o APK de teste é criado. 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 Configurações de Wi-Fi, o pacote de teste é
android.platform.tests
e o nome da classe de teste éWifiSettingTest
.
Biblioteca de snippets automotivos
A biblioteca de snippets automotivos é um conjunto de bibliotecas de teste do Android para os Android Open Source Project (AOSP) projetado para interagir com empresas automotivas e serviços do Google. Ele usa o Spectatio com um mecanismo conveniente para executar chamadas de procedimento remoto (RPCs) de uma máquina host (teste) para uma Dispositivo Android.
Primeiros passos
Antes de começar, leia estas seções.
Pré-requisitos
- Python 3.x instalado na máquina host.
- Configuração do ambiente AOSP com as ferramentas de build necessárias.
- Um dispositivo automotivo Android (emulador ou dispositivo físico) com acesso ao adb.
Compilação
Para compilar os diversos snippets fornecidos pela Biblioteca de snippets automotivos, você precisa
podem usar o arquivo android.bp
fornecido. Os comandos a seguir na API
para compilar o APK.
Implantação
Após compilar as bibliotecas de snippets, implante os APKs resultantes em
no dispositivo de destino usando o comando adb install
mencionado na
nesta seção.
Executar testes
As bibliotecas de snippets expõem vários métodos RPC para interagir com a interface
sistema. Esses métodos podem ser invocados pelo framework do Mobly a partir do host
máquina virtual. Supondo que o ambiente de teste do Mobly esteja configurado, você pode usar o
o script snippet_shell.py
para abrir um shell interativo do Python, em que é possível
invocar manualmente os métodos de 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 conseguir com
Dispositivos adb se vários dispositivos estiverem conectados.
Bibliotecas incluídas
A Biblioteca de snippets automotivos inclui as seguintes bibliotecas de snippets e auxiliares:
AutomotiveSnippet: oferece APIs relacionadas a operações com veículos, como discagem, controle de volume, teclas de hardware do veículo e interação com a central de mídia.
PhoneSnippet: oferece APIs relacionadas à telefonia, incluindo gerenciamento de chamadas, navegação de contatos e operações de SMS.
O snippet do Automotive e o PhoneSnippet compartilham uma lógica em comum.
Especificamente, você pode invadir chamadas RCP relacionadas ao Bluetooth para parear um dispositivo
e um telefone. Este bt_discovery_test
mostra como fazer isso.
- TEST-CLASSNAME: o nome da classe de teste. Por exemplo, para o
teste das Configurações de Wi-Fi,
o pacote de teste é
android.platform.tests
, e o nome da classe de teste éWifiSettingTest
.