Spectatio: Estrutura de testes automotivos

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.

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.

Arquitetura de alto nível da estrutura Spectatio

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

A interface 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 auxiliares do aplicativo para testar várias operações relacionadas ao aplicativo. Use a classe HelperAccessor para obter acesso às funções de implementação auxiliar do 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 application
    autoApplicationHelper.open();
  }

  @After
  public void afterTest() {
    // Cleanup after each test.
    // For example - exit the application
    autoApplicationHelper.exit();
  }

  @Test
  public void testApplicationFeature() {
    // Test
    // For example - Test if application 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 IU

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 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 o suficiente 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 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 assume a mesma forma que uma entrada do UI Element (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:

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

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

    OU,
  • THREE_QUARTER , HALF ou QUARTER : O gesto de deslizar termina cinco (5) pixels da borda da tela e começa no ponto que cobre a distância indicada da tela.
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 arquivo Android.bp . O nome do APK pode ser encontrado no respectivo arquivo Android.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.

Começando

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.