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 oferece APIs para testar apps em um dispositivo automotivo e é uma solução extensível e escalonável usada para verificar a capacidade e a performance do AAOS e dos apps dele.

Design de alto nível

O framework Spectatio é adaptável e expansível para várias implementações de interface do AAOS. Ele é usado para testar a capacidade e a performance do AAOS em hardware de dispositivos, 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 oferece um conjunto de APIs para criar testes de interface que interagem com apps de 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 vários dispositivos, se compatíveis.

A Figura 1 mostra que o framework Spectatio é modularizado com base em apps de referência, como o app Telefone, o Medicenter e o app 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 de utilitários e padrões 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 em todos os apps. As classes auxiliares de utilitários fornecem utilitários, como leitura ou gravação de arquivos do dispositivo.

Arquitetura

Para fornecer um conjunto de APIs para criar testes de interface, o framework Spectatio implementa interfaces e auxiliares específicos do app, estendendo a classe auxiliar padrão atual 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 auxiliar do app fornece um modelo para a implementação de um auxiliar de app. Ela 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 auxiliar do app 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 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ários que carrega o arquivo de configuração JSON do dispositivo e atualiza as configurações do framework no momento da execução.

O módulo de implementação auxiliar do app é o núcleo do framework 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 a 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 auxiliar do app 'no AOSP.

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

O código a seguir mostra a configuração, a limpeza e a execução de um teste automotivo de exemplo.

@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 ele é escalonável para testar dispositivos com interfaces e hardware variados. Para alcançar essa escalonabilidade, o Spectatio usa configurações de dispositivo 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 da 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 de path, e precisa conter apenas as informações sobre as mudanças de interface do DUT. O restante dos elementos da interface usa os valores de configuração padrão fornecidos no framework.

Configurações de dispositivo padrão

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

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

    {
        "SETTINGS": {
                "APPLICATION_CONFIG": {
                        "SETTINGS_TITLE_TEXT": "Settings",
                        "SETTINGS_PACKAGE": "com.android.car.settings",
                        "SETTINGS_RRO_PACKAGE": "com.android.car.settings.googlecarui.rro",
                        "OPEN_SETTINGS_COMMAND": "am start -a android.settings.SETTINGS",
                        "OPEN_QUICK_SETTINGS_COMMAND": "am start -n com.android.car.settings/com.android.car.settings.common.CarSettingActivity"
                },
                "QUICK_SETTINGS": {
                        "OPEN_MORE_SETTINGS": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "toolbar_menu_item_1",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "NIGHT_MODE": {
                                "TYPE": "TEXT",
                                "VALUE": "Night mode"
                        }
                },
                "DISPLAY": {
                        "PATH": "Settings > Display",
                        "OPTIONS": [
                                "Brightness level"
                        ],
                        "BRIGHTNESS_LEVEL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "seekbar",
                                "PACKAGE": "com.android.car.settings"
                        }
                },
                "SOUND": {
                        "PATH": "Settings > Sound",
                        "OPTIONS": [
                                "Media volume",
                                "Alarm volume"
                        ]
                },
                "NETWORK_AND_INTERNET": {
                        "PATH": "Settings > Network & internet",
                        "OPTIONS": [
                        ],
                        "TOGGLE_WIFI": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "master_switch",
                                "PACKAGE": "com.android.car.settings"
                        }
                },
                "BLUETOOTH": {
                        "PATH": "Settings > Bluetooth",
                        "OPTIONS": [
                        ],
                        "TOGGLE_BLUETOOTH": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_menu_item_switch",
                                "PACKAGE": "com.android.car.settings"
                        }
                },
                "APPS_AND_NOTIFICATIONS": {
                        "PATH": "Settings > Apps & notifications",
                        "OPTIONS": [
                        ],
                        "SHOW_ALL_APPS": {
                                "TYPE": "TEXT",
                                "VALUE": "Show all apps"
                        },
                        "ENABLE_DISABLE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_menu_item_text",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "DISABLE_BUTTON_TEXT": {
                                "TYPE": "TEXT",
                                "VALUE": "Disable"
                        },
                        "ENABLE_BUTTON_TEXT": {
                                "TYPE": "TEXT",
                                "VALUE": "Enable"
                        },
                        "DISABLE_APP_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "DISABLE APP"
                        },
                        "FORCE_STOP_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Force stop"
                        },
                        "OK_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "OK"
                        },
                        "PERMISSIONS_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Permissions"
                        },
                        "ALLOW_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Allow"
                        },
                        "DENY_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Deny"
                        },
                        "DENY_ANYWAY_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Deny anyway"
                        }
                },
                "DATE_AND_TIME": {
                        "PATH": "Settings > Date & time",
                        "OPTIONS": [
                                "Automatic date & time",
                "Automatic time zone"
                        ],
                        "AUTOMATIC_DATE_AND_TIME": {
                                "TYPE": "TEXT",
                                "VALUE": "Automatic date & time"
                        },
                        "AUTOMATIC_TIME_ZONE": {
                                "TYPE": "TEXT",
                                "VALUE": "Automatic time zone"
                        },
                        "SET_DATE": {
                                "TYPE": "TEXT",
                                "VALUE": "Set date"
                        },
                        "SET_TIME": {
                                "TYPE": "TEXT",
                                "VALUE": "Set time"
                        },
                        "SELECT_TIME_ZONE": {
                                "TYPE": "TEXT",
                                "VALUE": "Select time zone"
                        },
                        "USE_24_HOUR_FORMAT": {
                                "TYPE": "TEXT",
                                "VALUE": "Use 24-hour format"
                        },
                        "OK_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "toolbar_menu_item_0",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "NUMBER_PICKER_WIDGET": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.NumberPicker"
                        },
                        "EDIT_TEXT_WIDGET": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        }
                },
                "USERS": {
                        "PATH": "Settings > Users",
                        "OPTIONS": [
                                "Guest"
                        ]
                },
                "ACCOUNTS": {
                        "PATH": "Settings > Accounts",
                        "OPTIONS": [
                                "Automatically sync data"
                        ],
                        "ADD_ACCOUNT": {
                                "TYPE": "TEXT",
                                "VALUE": "ADD ACCOUNT"
                        },
                        "ADD_GOOGLE_ACCOUNT": {
                                "TYPE": "TEXT",
                                "VALUE": "Google"
                        },
                        "SIGN_IN_ON_CAR_SCREEN": {
                                "TYPE": "TEXT",
                                "VALUE": "Sign in on car screen"
                        },
                        "GOOGLE_SIGN_IN_SCREEN": {
                                "TYPE": "TEXT",
                                "VALUE": "Sign in to your Google Account"
                        },
                        "ENTER_EMAIL": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        },
                        "ENTER_PASSWORD": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        },
                        "NEXT_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Next"
                        },
                        "DONE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Done"
                        },
                        "REMOVE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Remove"
                        },
                        "REMOVE_ACCOUNT_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Remove Account"
                        }
                },
                "SYSTEM": {
                        "PATH": "Settings > System",
                        "OPTIONS": [
                                "About", "Legal information"
                        ],
                        "ABOUT_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "About"
                        },
                        "RESET_OPTIONS_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Reset options"
                        },
                        "LANGUAGES_AND_INPUT_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Languages & input"
                        },
                        "DEVICE_MODEL": {
                                "TYPE": "TEXT",
                                "VALUE": "Model"
                        },
                        "ANDROID_VERSION": {
                                "TYPE": "TEXT",
                                "VALUE": "Android version"
                        },
                        "ANDROID_SECURITY_PATCH_LEVEL": {
                                "TYPE": "TEXT",
                                "VALUE": "Android security patch level"
                        },
                        "KERNEL_VERSION": {
                                "TYPE": "TEXT",
                                "VALUE": "Kernel version"
                        },
                        "BUILD_NUMBER": {
                                "TYPE": "TEXT",
                                "VALUE": "Build number"
                        },
                        "RECYCLER_VIEW_WIDGET": {
                                "TYPE": "CLASS",
                                "VALUE": "androidx.recyclerview.widget.RecyclerView"
                        },
                        "RESET_NETWORK": {
                                "TYPE": "TEXT",
                                "VALUE": "Reset network"
                        },
                        "RESET_SETTINGS": {
                                "TYPE": "TEXT",
                                "VALUE": "RESET SETTINGS"
                        },
                        "RESET_APP_PREFERENCES": {
                                "TYPE": "TEXT",
                                "VALUE": "Reset app preferences"
                        },
                        "RESET_APPS": {
                                "TYPE": "TEXT",
                                "VALUE": "RESET APPS"
                        },
                        "LANGUAGES_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Languages"
                        },
                        "LANGUAGES_MENU_IN_SELECTED_LANGUAGE": {
                                "TYPE": "TEXT",
                                "VALUE": "Idiomas"
                        }
                },
                "SECURITY": {
                        "PATH": "Settings > Security",
                        "OPTIONS": [
                        ],
                        "TITLE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_title",
                                "PACKAGE": "com.android.car.settings.googlecarui.rro"
                        },
                        "CHOOSE_LOCK_TYPE": {
                                "TYPE": "TEXT",
                                "VALUE": "Choose a lock type"
                        },
                        "LOCK_TYPE_PASSWORD": {
                                "TYPE": "TEXT",
                                "VALUE": "Password"
                        },
                        "LOCK_TYPE_PIN": {
                                "TYPE": "TEXT",
                                "VALUE": "PIN"
                        },
                        "LOCK_TYPE_NONE": {
                                "TYPE": "TEXT",
                                "VALUE": "None"
                        },
                        "CONTINUE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Continue"
                        },
                        "CONFIRM_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Confirm"
                        },
                        "ENTER_PASSWORD": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        },
                        "PIN_PAD": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "pin_pad",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "ENTER_PIN_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "key_enter",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "REMOVE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Remove"
                        }
                }
        },
        "PHONE": {
                "APPLICATION_CONFIG": {
                        "DIAL_PACKAGE": "com.android.car.dialer",
                        "PHONE_ACTIVITY": "com.android.car.dialer/.ui.TelecomActivity",
                        "OPEN_DIAL_PAD_COMMAND": "am start -a android.intent.action.DIAL"
                },
                "IN_CALL_VIEW": {
                        "DIALED_CONTACT_TITLE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "user_profile_title",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "DIALED_CONTACT_NUMBER": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "user_profile_phone_number",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "END_CALL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "end_call_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "MUTE_CALL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "mute_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "SWITCH_TO_DIAL_PAD": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "toggle_dialpad_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CHANGE_VOICE_CHANNEL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "voice_channel_view",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "VOICE_CHANNEL_CAR": {
                                "TYPE": "TEXT",
                                "VALUE": "Car speakers"
                        },
                        "VOICE_CHANNEL_PHONE": {
                                "TYPE": "TEXT",
                                "VALUE": "Phone"
                        }
                },
                "DIAL_PAD_VIEW": {
                        "DIAL_PAD_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Dial Pad"
                        },
                        "DIAL_PAD_FRAGMENT": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "dialpad_fragment",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "DIALED_NUMBER": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "MAKE_CALL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "call_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "DELETE_NUMBER": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "delete_button",
                                "PACKAGE": "com.android.car.dialer"
                        }
                },
                "CONTACTS_VIEW": {
                        "CONTACTS_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Contacts"
                        },
                        "CONTACT_INFO": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "call_action_id",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_DETAIL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "show_contact_detail_id",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "ADD_CONTACT_TO_FAVORITE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "contact_details_favorite_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "SEARCH_CONTACT": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "menu_item_search",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_SEARCH_BAR": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_search_bar",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "SEARCH_RESULT": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "contact_name",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_SETTINGS": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "menu_item_setting",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_ORDER": {
                                "TYPE": "TEXT",
                                "VALUE": "Contact order"
                        },
                        "SORT_BY_FIRST_NAME": {
                                "TYPE": "TEXT",
                                "VALUE": "First name"
                        },
                        "SORT_BY_LAST_NAME": {
                                "TYPE": "TEXT",
                                "VALUE": "Last Name"
                        },
                        "CONTACT_TYPE_WORK": {
                                "TYPE": "TEXT",
                                "VALUE": "Work"
                        },
                        "CONTACT_TYPE_MOBILE": {
                                "TYPE": "TEXT",
                                "VALUE": "Mobile"
                        },
                        "CONTACT_TYPE_HOME": {
                                "TYPE": "TEXT",
                                "VALUE": "Home"
                        }
                },
                "CALL_HISTORY_VIEW": {
                        "CALL_HISTORY_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Recents"
                        },
                        "CALL_HISTORY_INFO": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "call_action_id",
                                "PACKAGE": "com.android.car.dialer"
                        }
                },
                "FAVORITES_VIEW": {
                        "FAVORITES_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Favorites"
                        }
                }
        },
        "NOTIFICATIONS": {
                "APPLICATION_CONFIG": {
                        "OPEN_NOTIFICATIONS_COMMAND": "service call statusbar 1"
                },
                "EXPANDED_NOTIFICATIONS_SCREEN": {
                        "NOTIFICATION_VIEW": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "notification_view",
                                "PACKAGE": "com.android.systemui"
                        },
                        "CLEAR_ALL_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "clear_all_button",
                                "PACKAGE": "com.android.systemui"
                        },
                        "STATUS_BAR": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_top_navigation_bar_container",
                                "PACKAGE": "com.android.systemui"
                        },
                        "APP_ICON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "app_icon",
                                "PACKAGE": "com.android.systemui"
                        },
                        "APP_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "header_text",
                                "PACKAGE": "com.android.systemui"
                        },
                        "NOTIFICATION_TITLE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "notification_body_title",
                                "PACKAGE": "com.android.systemui"
                        },
                        "NOTIFICATION_BODY": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "notification_body_content",
                                "PACKAGE": "com.android.systemui"
                        },
                        "CARD_VIEW": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "card_view",
                                "PACKAGE": "com.android.systemui"
                        }
                }
        },
        "MEDIA_CENTER": {
                "APPLICATION_CONFIG": {
                        "MEDIA_CENTER_PACKAGE": "com.android.car.media",
                        "MEDIA_ACTIVITY": "com.android.bluetooth/com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService"
                },
                "MEDIA_CENTER_SCREEN": {
                        "PLAY_PAUSE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "play_pause_stop",
                                "PACKAGE": "com.android.car.media"
                        },
                        "NEXT_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_next",
                                "PACKAGE": "com.android.car.media"
                        },
                        "PREVIOUS_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_prev",
                                "PACKAGE": "com.android.car.media"
                        },
                        "SHUFFLE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "overflow_on",
                                "PACKAGE": "com.android.car.media"
                        },
                        "PLAY_QUEUE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "play_queue",
                                "PACKAGE": "com.android.car.media"
                        },
                        "MINIMIZED_MEDIA_CONTROLS": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "minimized_playback_controls",
                                "PACKAGE": "com.android.car.media"
                        },
                        "TRACK_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.media"
                        },
                        "TRACK_NAME_MINIMIZED_CONTROL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "minimized_control_bar_title",
                                "PACKAGE": "com.android.car.media"
                        },
                        "BACK_BUTTON": {
                                "TYPE": "DESCRIPTION",
                                "VALUE": "Back"
                        }
                },
                "MEDIA_CENTER_ON_HOME_SCREEN": {
                        "PLAY_PAUSE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "play_pause_stop",
                                "PACKAGE": "com.android.car.carlauncher"
                        },
                        "NEXT_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_next",
                                "PACKAGE": "com.android.car.carlauncher"
                        },
                        "PREVIOUS_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_prev",
                                "PACKAGE": "com.android.car.carlauncher"
                        },
                        "TRACK_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.carlauncher"
                        }
                }
        }
}
  

Configurações alternativas do dispositivo

O exemplo de código a seguir mostra um exemplo do arquivo de configuração JSON em que as configurações padrão são substituídas pelas configurações no DUT. Neste exemplo:

  • As configurações de Internet são chamadas de Rede e Internet em dispositivos de referência e Conectividade no DUT.

  • As configurações de data e hora estão disponíveis em Configurações > Data e hora 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 bloco de código a seguir:

# 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 serial do DUT. Esse parâmetro não é obrigató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 de ação e parâmetros para várias ações. Por exemplo, se você quer usar botões ou um gesto para rolar.
COMMANDS Um objeto que especifica comandos que realizam várias ações.
UI_ELEMENTS Um objeto usado para construir `BySelectors` do UI Automator que selecionam elementos de 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 arbitrário será usado no teste. Portanto, a configuração precisa (geralmente) ser escrita de forma específica o suficiente para restringir a um elemento no contexto relevante.

TEXT

Esse é o tipo de elemento da 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 no texto do elemento para ser correspondente.

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

DESCRIPTION

Identifica 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

Identifica o elemento pelo ID do recurso, também verificando opcionalmente o componente do pacote desse ID. A chave PACKAGE é opcional. Se omitida, qualquer pacote vai 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"
    }

CLICKABLE, SCROLLABLE

Identifica o elemento com base em se ele é (ou não) clicável ou rolável. Esses são tipos de elementos muito amplos e geralmente só devem ser usados em um MULTIPLE para ajudar a restringir outro tipo de elemento. A chave FLAG é opcional e o padrão é true.

    "SAMPLE_ELEMENT": {
      "TYPE": "CLICKABLE",
      "FLAG": false
    }

CLASS

Identifica o elemento com base na classe dele.

    "SECURITY_SETTINGS_ENTER_PASSWORD": {
      "TYPE": "CLASS",
      "VALUE": "android.widget.EditText"
    }

HAS_ANCESTOR

Identifica o elemento pesquisando a hierarquia de widgets nos ancestrais dele. A chave ANCESTOR contém um objeto que identifica o ancestral. A chave DEPTH especifica até onde na hierarquia procurar. 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

Identifica o elemento pesquisando a hierarquia nos filhos dele. A chave DESCENDANT contém um objeto que especifica o filho a ser procurado. A chave DEPTH especifica até onde na hierarquia procurar. DEPTH é opcional e tem um valor padrão de 1.

      "SAMPLE_ELEMENT": {
      "TYPE": "HAS_DESCENDANT",
      "DEPTH": 2,
      "DESCENDANT": {
        "TYPE": "CLASS",
        "VALUE": "android.view.ViewGroup"
      }
    }

MULTIPLE

Identifica o elemento com base em várias condições simultâneas, todas as quais 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.

Fluxos de trabalho

Um fluxo de trabalho representa uma sequência de ações usadas para realizar uma tarefa específica, que pode ser suficientemente diferente de um tipo de dispositivo para outro 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 o mesmo formato de uma entrada de elemento de interface (consulte acima). Esses TYPEs 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 da 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 a CONFIG key para uma ação SWIPE. Isto usa apenas SWIPE_CONFIG.
WAIT_MS Um objeto com um valor TEXT que contém o número de milissegundos a serem aguardados.

As ações relacionadas a rolagem e deslize exigem configuração adicional, da seguinte maneira:

SCROLL_CONFIG

Objeto Descrição
SCROLL_ACTION USE_GESTURE ou USE_BUTTON
SCROLL_DIRECTION HORIZONTAL ou VERTICAL
SCROLL_ELEMENT Um objeto que indica o contêiner a ser rolado, usando o mesmo formato de uma configuração de elemento de interface (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 parar o arrastar que será usado para realizar a rolagem (Opcional, padrão = 10).
SCROLL_WAIT_TIME Se SCROLL_ACTION for USE_GESTURE, o tempo em milissegundos para aguardar entre os 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

Um dos seguintes:

  • FULL: gesto de deslize da borda da tela até a borda da tela

    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 deslize 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 deslize. Consulte segmentSteps.

Criar e executar

O framework Spectatio é criado automaticamente como parte do APK de teste. Para criar o APK de teste, a base de código do AOSP precisa estar 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 a seguir mostra a criação, a instalação e a execução de um APK de teste.

# Build Test APK
make TEST-APK-NAME
# Install Test APK
adb -s DEVICE-SERIAL install -r PATH-FOR-BUILT-TEST-APK
# Execute Test with the JSON file
adb -s DEVICE-SERIAL shell am instrument -w -r -e debug false -e config-file-path /data/local/tmp/jsonFile.json -e class TEST-PACKAGE.TEST-CLASSNAME TEST-PACKAGE/androidx.test.runner.AndroidJUnitRunner

Nesses comandos:

  • TEST-APK-NAME: o nome do app a ser testado. Por exemplo, defina TEST-APK-NAME como AndroidAutomotiveSettingsTests para testar as configurações de Wi-Fi conforme especificado no Android.bp arquivo. O nome do APK pode ser encontrado no arquivo Android.bp respectivo para o teste automotivo.

  • DEVICE-SERIAL: o ID serial do DUT. Esse parâmetro não é obrigatório se apenas um dispositivo estiver conectado ao host.

  • config-file-path: parâmetro opcional necessário apenas para fornecer configurações de interface do dispositivo não padrão, conforme especificado no arquivo de configuração JSON. Se não for fornecido, o framework usará os 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 de configurações de Wi-Fi, o pacote de teste é android.platform.tests e o nome da classe de teste é WifiSettingTest.

Biblioteca de snippets automotivos

A Biblioteca de snippets automotivos é um conjunto de bibliotecas de teste do Android para o Android Open Source Project (AOSP) projetado para interagir com apps e serviços automotivos. Ela aproveita 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 adb.

Compilação

Para compilar os vários snippets fornecidos pela Biblioteca de snippets automotivos, você pode usar o arquivo android.bp fornecido. Siga os comandos na seção anterior para compilar o APK.

Implantação

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

Executar testes

As bibliotecas de snippets 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 o ambiente de teste do Mobly configurado, use o snippet_shell.py script para abrir um shell Python interativo, 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 obtido com adb devices se vários dispositivos estiverem conectados.

Bibliotecas incluídas

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

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

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

O snippet automotivo e o PhoneSnippet compartilham algumas lógicas comuns. Especificamente, é possível invadir chamadas RCP relacionadas ao Bluetooth para parear um dispositivo automotivo e um telefone. Este bt_discovery_test mostra como.