Spectatio: framework de teste automotivo

O Spectatio é um framework de teste de código aberto desenvolvido para testar o Android Automotive OS (AAOS) em dispositivos reais e virtuais. O Spectatio fornece APIs para testar 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.

Design de alto nível

O framework Spectatio é adaptável e expansível para várias implementações de interface AAOS. Ele é usado para testar o recurso e o desempenho do AAOS em hardware de dispositivo, emuladores e ambientes virtualizados.

A figura a seguir explica o design de alto nível do framework Spectatio.

Design de alto nível do framework Spectatio

Figura 1. Design de alto nível do framework Spectatio.

Criado com base no UI Automator, o framework Spectatio fornece um conjunto de APIs para criar testes de interface que interagem com apps do usuário e do sistema no AAOS. Os testes automotivos usam as APIs fornecidas pelo framework Spectatio para testes, o que torna esses testes independentes do dispositivo em teste (DUT, na sigla em inglês) e escalonáveis para testar dispositivos variados, se houver suporte.

A Figura 1 mostra que o framework Spectatio é modularizado com base em apps de referência como Discador, Medicenter e Configurações, usando interfaces e auxiliares específicos do app, o que facilita a extensão para novos apps. O framework Spectatio reutiliza as classes auxiliares padrão e utilitárias comuns. A classe auxiliar padrão é a classe mãe de todas as funções auxiliares do app e fornece funções padrão específicas do dispositivo ou aplicáveis a vários apps. As classes auxiliares de utilitários oferecem utilitários, como ler ou gravar arquivos do dispositivo.

Arquitetura

Para fornecer um conjunto de APIs para criar testes de IU, o framework Spectatio implementa interfaces e auxiliares específicos do app, estendendo a classe auxiliar padrão e importando as classes auxiliares de utilitários.

A Figura 2 ilustra a arquitetura de alto nível do framework Spectatio e todas as entidades envolvidas na implementação de APIs para testar um app.

Arquitetura de alto nível do framework Spectatio

Figura 2. Arquitetura de alto nível do framework Spectatio.

A interface do App Helper fornece um modelo para a implementação de um App Helper. Ele consiste em várias funções auxiliares 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 de interface auxiliares 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ários são usadas pelo framework. Por exemplo, AutoJsonUtility.java é uma classe de utilitário que carrega o arquivo de configuração JSON do dispositivo e atualiza as configurações do framework no tempo de execução.

O módulo de implementação do assistente do app é o núcleo do framework da Spectatio. Ele contém a implementação das funções auxiliares definidas na interface auxiliar do app, que são necessárias para testar apps em um dispositivo automotivo. Cada app tem sua própria implementação, como SettingHelperImpl e DialHelperImpl, usada pelos testes automotivos para testar os apps. Para mais informações e uma lista de implementações, consulte as funções de implementação do app helper no AOSP.

Os testes automotivos usam as funções de implementação do assistente do app para testar várias operações relacionadas ao app. Use a classe HelperAccessor para ter acesso às funções de implementação do assistente do app.

O código abaixo mostra a configuração, a limpeza e a 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());
  }
}

Personalização

O framework Spectatio é independente da interface do dispositivo, então é escalonável para testar dispositivos com interfaces e hardwares variados. Para alcançar essa escalabilidade, o Spectatio usa configurações padrão com base no dispositivo de referência. Para oferecer suporte a configurações de dispositivo não padrão, o framework usa um arquivo de configuração JSON no momento de execução para definir as mudanças de interface desejadas para o dispositivo. Um arquivo de configuração JSON oferece suporte a elementos de interface, como TEXT, DESCRIPTION e RESOURCE_ID, além de configurações path e precisa conter apenas as informações sobre as mudanças na interface do DUT. O restante dos elementos da interface usam os valores de configuração padrão fornecidos no framework.

Configurações padrão do dispositivo

O exemplo de arquivo de configuração JSON abaixo mostra as configurações de dispositivo disponíveis e os valores padrão.

Clique aqui para mostrar um arquivo de configuração JSON de amostra

    {
        "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 abaixo 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 nomeadas como 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 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 no momento da 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

Nesse comando:

  • DEVICE-SERIAL: ID do serial do DUT. Esse 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

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 apps, que são usados para determinar quando esse app está em primeiro plano.
ACTIONS Um objeto que indica tipos e parâmetros de várias ações. Por exemplo, se é melhor usar botões ou um gesto para rolar.
COMMANDS Um objeto que especifica comandos que executam várias ações.
UI_ELEMENTS Um objeto usado para construir "BySelectors" do UI Automator que selecionam elementos da interface (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 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 auxiliar identifica um elemento na tela usando essa configuração, ele recebe exatamente um elemento. Se vários elementos corresponderem à configuração, um deles será usado no teste. Portanto, a configuração precisa ser escrita de forma específica para que se restrinja a um elemento no contexto relevante.

TEXT

Esse é o tipo de elemento de interface mais simples. O elemento da interface é identificado pelo texto e exige uma correspondência exata.

    "CALL_HISTORY_MENU": {
      "TYPE": "TEXT",
      "VALUE": "Recents"
    }

TEXT_CONTAINS

Igual a TEXT, exceto que o VALUE especificado só precisa aparecer em algum lugar do texto do elemento a ser correspondido.

    "PRIVACY_CALENDAR": {
      "TYPE": "TEXT_CONTAINS",
      "VALUE": "Calendar"
    }

DESCRIÇÃO

Identifique o elemento pelo atributo de descrição do conteúdo, exigindo uma correspondência exata.

    "APP_GRID_SCROLL_BACKWARD_BUTTON": {
      "TYPE": "DESCRIPTION",
      "VALUE": "Scroll up"
    }

RESOURCE_ID

Identifique o elemento pelo ID do recurso, opcionalmente, verificando também o componente do pacote desse ID. A chave PACKAGE é opcional. Se for omitida, qualquer pacote será correspondente, 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 na possibilidade de clicar ou rolar. Esses são tipos de elementos muito amplos e geralmente devem ser usados apenas 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"
    }

HAS_ANCESTOR

Identifique o elemento procurando a hierarquia do widget nos ancestrais dele. A chave ANCESTOR contém um objeto que identifica o ancestral. A chave DEPTH especifica até onde a hierarquia precisa ser analisada. 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 procurando pelos filhos na hierarquia. A chave DESCENDANT contém um objeto que especifica o filho a ser procurado. A chave DEPTH especifica até onde a hierarquia precisa ser analisada. 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ÁRIAS

Identifique o elemento com base em várias condições simultâneas, que precisam 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 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 tarefa específica, que pode variar bastante de acordo com o 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 de chave-valor em que a chave é o nome do fluxo de trabalho e o valor é uma matriz de ações a serem realizadas. Cada ação tem 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 tem a mesma forma que uma entrada de elemento da interface (consulte acima). Esses TIPOS são:

PRESS
LONG_PRESS
CLICK
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 outros TYPEs, 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. Ele usa apenas SWIPE_CONFIG
WAIT_MS Um objeto com um valor TEXT contendo o número de milissegundos a serem aguardados.

As ações relacionadas a rolagem e deslizamento exigem uma configuração extra, conforme descrito abaixo:

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 a mesma forma que uma configuração de elemento da IU (consulte acima).
SCROLL_FORWARD, SCROLL_BACKWARD Os botões de rolagem para frente e para trás (obrigatório quando SCROLL_ACTION é USE_BUTTON).
SCROLL_MARGIN Se SCROLL_ACTION for USE_GESTURE, a distância da borda do contêiner para iniciar e interromper o arrasto que será usado para rolar (Opcional,padrão = 10).
SCROLL_WAIT_TIME Se SCROLL_ACTION for USE_GESTURE, o tempo em milissegundos para aguardar entre gestos de rolagem ao procurar um objeto para clicar. (Opcional,padrão = 1).

SWIPE_CONFIG

Objeto Descrição
SWIPE_DIRECTION TOP_TO_BOTTOM, BOTTOM_TO_TOP, LEFT_TO_RIGHT ou RIGHT_TO_LEFT
SWIPE_FRACTION

Uma das seguintes opções:

  • FULL: gesto de deslizar da borda de uma tela para a outra

    OU,
  • DEFAULT: borda da tela até a borda da tela, com um buffer de cinco (5) pixels em cada lado.

    OU,
  • THREE_QUARTER, HALF ou QUARTER: o gesto de deslizar termina a cinco (5) pixels da borda da tela e começa no ponto de modo que cubra a distância indicada da tela.
NUMBER_OF_STEPS O número de etapas a serem usadas para realizar o deslizar. Consulte segmentSteps.

Criar e executar

O framework Spectatio é criado automaticamente como parte do APK de teste. Para criar o APK de teste, o código-base do AOSP precisa residir na estação de trabalho local. Depois que o APK de teste é criado, o usuário precisa instalar o APK no dispositivo e executar o teste.

O exemplo de código abaixo 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 TEST-APK-NAME como AndroidAutomotiveSettingsTests para testar as configurações de Wi-Fi conforme especificado no arquivo Android.bp. O nome do APK pode ser encontrado no arquivo Android.bp correspondente para o teste automotivo.

  • DEVICE-SERIAL: o ID do lote do DUT. Esse 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 IU do dispositivo não padrão, conforme especificado no arquivo de configuração JSON. Se não forem fornecidos, o framework vai usar 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 teste Configurações de Wi-Fi, o pacote de teste é android.platform.tests e o nome da classe de teste é WifiSettingTest.

Biblioteca de snippets de automóveis

A biblioteca de snippets automotivos é um conjunto de bibliotecas do Android Test para o Android Open Source Project (AOSP), projetado para interagir com apps e serviços automotivos. Ele usa o Spectatio com um mecanismo conveniente para executar chamadas de procedimento remoto (RPCs) de uma máquina host (de teste) para um 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 vários snippets fornecidos pela biblioteca de snippets automotivos, use o arquivo android.bp fornecido. Siga os comandos na seção anterior para compilar o APK.

Implantação

Depois de compilar as bibliotecas de snippet, implante os APKs resultantes no dispositivo de destino usando o comando adb install mencionado na seção anterior.

Executar testes

As bibliotecas de snippet expõem vários métodos RPC para interagir com o sistema automotivo. Esses métodos podem ser invocados pelo framework Mobly na máquina host. Supondo que você tenha configurado o ambiente de teste do Mobly, use o script snippet_shell.py para abrir um shell interativo do Python, em que é possível 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 pode ser encontrado com dispositivos adb se vários dispositivos estiverem conectados.

Bibliotecas incluídas

A Biblioteca de snippets automotivos inclui as seguintes bibliotecas e ajudantes de snippets:

  • AutomotiveSnippet: fornece APIs relacionadas a operações do veículo, como discagem, controle de volume, teclas físicas do veículo e interação com o centro de mídia.

  • PhoneSnippet: fornece APIs relacionadas à telefonia, incluindo processamento de chamadas, navegação de contatos e operações de SMS.

O snippet de automóveis e o PhoneSnippet compartilham uma lógica comum. Especificamente, é possível invadir chamadas RCP relacionadas ao Bluetooth para parear um dispositivo automotivo e um smartphone. Este bt_discovery_test mostra como.