Spectatio è un framework di test open source sviluppato per testare il sistema operativo Android Automotive (AAOS) su dispositivi reali e virtuali. Spectatio fornisce API per testare le app su un dispositivo automobilistico ed è una soluzione estensibile e scalabile utilizzata per verificare la capacità e le prestazioni di AAOS e delle sue app.
Progettazione di alto livello
Il framework Spectatio è adattabile ed espandibile per varie implementazioni dell'interfaccia utente AAOS. Viene utilizzato per testare la funzionalità e le prestazioni di AAOS sull'hardware del dispositivo, sugli emulatori e sugli ambienti virtualizzati.
La figura seguente spiega la progettazione di alto livello del framework Spectatio.
Figura 1. Progettazione di alto livello del quadro Spectatio.
Basato su UI Automator , il framework Spectatio fornisce una serie di API per creare test dell'interfaccia utente che interagiscono con le app utente e di sistema su AAOS. I test automobilistici utilizzano le API fornite dal framework Spectatio per i test, il che rende questi test indipendenti dal dispositivo sottoposto a test (DUT) e scalabili per testare vari dispositivi, se supportati.
La Figura 1 mostra che il framework Spectatio è modularizzato in base ad app di riferimento come Dialer, Medicenter e Impostazioni utilizzando interfacce e helper specifici dell'app, rendendolo facilmente estensibile per nuove app. Il framework Spectatio riutilizza le classi standard e di supporto di utilità comuni. La classe helper standard è la classe padre per tutte le funzioni helper dell'app e fornisce funzioni standard specifiche del dispositivo o applicabili a tutte le app. Le classi helper di utilità forniscono utilità come la lettura o la scrittura di file dal dispositivo.
Architettura
Per fornire una serie di API per creare test dell'interfaccia utente, il framework Spectatio implementa interfacce e helper specifici dell'app estendendo la classe helper standard esistente e importando le classi helper di utilità.
La Figura 2 illustra l'architettura di alto livello del framework Spectatio e tutte le entità coinvolte nell'implementazione delle API per testare un'app.
Figura 2. Architettura di alto livello del framework Spectatio.
L'interfaccia dell'helper dell'app fornisce un modello per l'implementazione di un helper dell'app. È costituito da varie funzioni di supporto necessarie per testare le app. Ogni app ha la propria interfaccia, ad esempio IAutoSettingHelper
e IAutoDialHelper
. Per ulteriori informazioni e un elenco delle funzioni dell'interfaccia, vedere le funzioni dell'interfaccia dell'helper dell'app su AOSP.
La classe helper standard è costituita da attributi e funzioni standard richiesti per la configurazione del dispositivo ma non specifici per alcuna app, ad esempio pressHome
e scroll
. La classe helper standard è definita in AbstractAutoStandardAppHelper.java
.
Le classi helper di utilità vengono utilizzate dal framework. Ad esempio, AutoJsonUtility.java
è una classe di utilità che carica il file di configurazione JSON del dispositivo specificato e aggiorna le configurazioni del framework in fase di runtime.
Il modulo di implementazione dell'helper dell'app è il nucleo del framework Spectatio. Contiene l'implementazione per le funzioni di supporto definite nell'interfaccia di supporto dell'app, necessarie per testare le app su un dispositivo automobilistico. Ogni app ha la propria implementazione, come SettingHelperImpl
e DialHelperImpl
, utilizzata dai test Automotive per testare le app. Per ulteriori informazioni e un elenco delle implementazioni, vedere le funzioni di implementazione dell'helper dell'app su AOSP.
I test automobilistici utilizzano le funzioni di implementazione dell'helper dell'app per testare varie operazioni relative all'app. Utilizza la classe HelperAccessor
per ottenere l'accesso alle funzioni di implementazione dell'helper dell'app.
Il codice seguente mostra la configurazione, la pulizia e l'esecuzione di un test automobilistico di esempio.
@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());
}
}
Personalizzazione
Il framework Spectatio è indipendente dall'interfaccia utente del dispositivo, quindi è scalabile per testare dispositivi con interfacce utente e hardware diversi. Per ottenere questa scalabilità, Spectatio utilizza configurazioni predefinite del dispositivo basate sul dispositivo di riferimento. Per supportare configurazioni del dispositivo non predefinite, il framework utilizza un file di configurazione JSON in fase di esecuzione per impostare le modifiche desiderate dell'interfaccia utente per il dispositivo. Un file di configurazione JSON supporta elementi dell'interfaccia utente come TEXT
, DESCRIPTION
e RESOURCE_ID
, insieme alle impostazioni path
e deve contenere solo le informazioni sulle modifiche dell'interfaccia utente per il DUT. Il resto degli elementi dell'interfaccia utente utilizzano i valori di configurazione predefiniti forniti nel framework.
Configurazioni predefinite del dispositivo
Il seguente file di configurazione JSON di esempio mostra le configurazioni dei dispositivi disponibili e i relativi valori predefiniti.
Fare clic qui per visualizzare un file di configurazione JSON di esempio
{ "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" } } } }
Configurazioni alternative del dispositivo
L'esempio di codice seguente mostra un esempio del file di configurazione JSON in cui le impostazioni predefinite vengono sovrascritte dalle impostazioni sul DUT. In questo esempio:
Le impostazioni Internet sono denominate Rete e Internet sui dispositivi di riferimento e Connettività sul DUT.
Le impostazioni di data e ora sono disponibili in Impostazioni > Data e ora per i dispositivi di riferimento e in Impostazioni > Sistema > Data e ora per il 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 il file di configurazione JSON è pronto, viene fornito in fase di esecuzione come mostrato nel seguente blocco di codice:
# Push The JSON configuration file to the device
adb -s DEVICE-SERIAL push PATH-OF-JSON-FILE /data/local/tmp/runtimeSpectatioConfig.json
In questo comando:
DEVICE-SERIAL : ID seriale del DUT. Questo parametro non è obbligatorio se all'host è connesso un solo dispositivo.
PATH-TO-JSON-FILE : percorso del file JSON sul computer host.
Formato di configurazione
Nella configurazione sono presenti cinque oggetti di primo livello, con le seguenti chiavi e valori:
Oggetto | Descrizione |
---|---|
PACKAGES | Un oggetto che descrive il pacchetto principale per varie app, utilizzato per determinare quando l'app è in primo piano. |
ACTIONS | Un oggetto che indica i tipi di azione e i parametri per varie azioni. Ad esempio, se utilizzare i pulsanti o un gesto per scorrere. |
COMMANDS | Un oggetto che specifica comandi che eseguono varie azioni. |
UI_ELEMENTS | Un oggetto utilizzato per costruire l'UI Automator "BySelectors" che seleziona gli elementi dell'interfaccia utente (descritti in dettaglio di seguito). |
WORKFLOWS | Sequenze di azioni che realizzano compiti di alto livello (descritti in dettaglio di seguito). |
Elementi dell'interfaccia utente
Ogni elemento dell'interfaccia utente ha un TYPE
che specifica cosa cercherà UI Automator per identificare l'elemento (come ID risorsa, testo e descrizione) e i valori di configurazione associati a quel tipo. In generale, ogni volta che un helper identifica un elemento sullo schermo utilizzando questa configurazione, ottiene esattamente un elemento. Se più elementi corrispondono alla configurazione, nel test ne viene utilizzato uno arbitrario. Pertanto, la configurazione dovrebbe (generalmente) essere scritta in modo sufficientemente specifico da restringere il campo a un elemento nel contesto pertinente.
TESTO
Questo è il tipo di elemento dell'interfaccia utente più semplice. L'elemento dell'interfaccia utente è identificato dal testo e richiede una corrispondenza esatta.
"CALL_HISTORY_MENU": {
"TYPE": "TEXT",
"VALUE": "Recents"
}
TESTO_CONTAINS
Uguale a TEXT
, tranne per il fatto che il VALUE
specificato deve solo apparire da qualche parte nel testo dell'elemento da abbinare.
"PRIVACY_CALENDAR": {
"TYPE": "TEXT_CONTAINS",
"VALUE": "Calendar"
}
DESCRIZIONE
Identificare l'elemento tramite l'attributo della descrizione del contenuto, richiedendo una corrispondenza esatta.
"APP_GRID_SCROLL_BACKWARD_BUTTON": {
"TYPE": "DESCRIPTION",
"VALUE": "Scroll up"
}
RISORSA_ID
Identificare l'elemento in base al relativo ID risorsa, facoltativamente controllando anche il componente pacchetto di tale ID. Il tasto PACKAGE
è facoltativo; se omesso, qualsiasi pacchetto corrisponderà e verrà considerata solo la parte dell'ID che segue :id/
.
"APP_LIST_SCROLL_ELEMENT": {
"TYPE": "RESOURCE_ID",
"VALUE": "apps_grid",
"PACKAGE": "com.android.car.carlauncher"
}
CLICCABILE, SCORRIBILE
Identificare l'elemento in base al fatto che sia (o meno) cliccabile o scorrevole. Questi sono tipi di elementi molto ampi e generalmente dovrebbero essere utilizzati solo in MULTIPLE
per restringere il campo di un altro tipo di elemento. La chiave FLAG
è facoltativa e il valore predefinito è true
.
"SAMPLE_ELEMENT": {
"TYPE": "CLICKABLE",
"FLAG": false
}
CLASSE
Identificare l'elemento in base alla sua classe.
"SECURITY_SETTINGS_ENTER_PASSWORD": {
"TYPE": "CLASS",
"VALUE": "android.widget.EditText"
}
HAS_ANTE
Identificare l'elemento cercando nella gerarchia dei widget i suoi antenati. La chiave ANCESTOR
contiene un oggetto che identifica l'antenato. La chiave DEPTH
specifica quanto in alto nella gerarchia cercare. DEPTH
è facoltativo e ha un valore predefinito pari a 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_ANCESTOR",
"DEPTH": 2,
"ANCESTOR": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
HAS_DESCENDANTE
Identificare l'elemento osservando i suoi figli lungo la gerarchia. La chiave DESCENDANT
contiene un oggetto che specifica il figlio da cercare. La chiave DEPTH
specifica quanto in alto nella gerarchia cercare. DEPTH
è facoltativo e ha un valore predefinito pari a 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_DESCENDANT",
"DEPTH": 2,
"DESCENDANT": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
MULTIPLI
Identificare l'elemento in base a più condizioni simultanee, che devono essere tutte soddisfatte.
"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"
}
}
]
}
In questo esempio, la configurazione identifica un RelativeLayout
che ha un discendente alla profondità 2
, che ha il testo Permission manager
.
Flussi di lavoro
Un flusso di lavoro rappresenta una sequenza di azioni utilizzate per eseguire una particolare attività, che può differire abbastanza da tipo di dispositivo a tipo di dispositivo ed è più flessibile da rappresentare nella configurazione che nel codice.
"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"
}
}
}
]
}
Ogni flusso di lavoro è una coppia chiave-valore in cui la chiave è il nome del flusso di lavoro e il valore è una serie di azioni da eseguire. Ogni azione ha un NAME
, un TYPE
, (di solito) un CONFIG
e (a volte) un SWIPE_CONFIG
o SCROLL_CONFIG
. Per la maggior parte dei TYPE, CONFIG
è un oggetto con una chiave UI_ELEMENT
il cui valore assume la stessa forma di una voce di elemento UI (vedi sopra). Questi TIPI sono:
PREMERE PREMERE A LUNGO CLIC LUNGO_CLIC CLICCA_IF_EXIST | HAS_UI_ELEMENT_IN_FOREGROUND SCORRI_PER_TROVARE_E_CLICCA SCROLL_TO_FIND_AND_CLICK_IF_EXIST SCORRI_PER_TROVARE_E_CLICCA SWIPE_TO_FIND_AND_CLICK_IF_EXIST |
Per le altre TIPOLOGIE i dettagli di configurazione sono:
Oggetto | Descrizione |
---|---|
COMMAND | Un oggetto con un valore TEXT contenente il comando da eseguire. |
HAS_PACKAGE_IN_FOREGROUND | Un oggetto con un valore TEXT contenente il pacchetto. |
SWIPE | Omettere il CONFIG key per un'azione SWIPE . Questo utilizza solo SWIPE_CONFIG |
WAIT_MS | Un oggetto con un valore TEXT contenente il numero di millisecondi da attendere. |
Le azioni relative allo scorrimento e allo scorrimento richiedono una configurazione aggiuntiva, come segue:
SCROLL_CONFIG
Oggetto | Descrizione |
---|---|
SCROLL_ACTION | O USE_GESTURE o USE_BUTTON |
SCROLL_DIRECTION | Sia HORIZONTAL che VERTICAL |
SCROLL_ELEMENT | Un oggetto che indica il contenitore da scorrere, utilizzando lo stesso modulo della configurazione dell'elemento UI (vedi sopra). |
SCROLL_FORWARD , SCROLL_BACKWARD | I pulsanti di scorrimento avanti e indietro (richiesti quando SCROLL_ACTION è USE_BUTTON ). |
SCROLL_MARGIN | Se SCROLL_ACTION è USE_GESTURE , la distanza dal bordo del contenitore per iniziare e interrompere il trascinamento che verrà utilizzato per eseguire lo scorrimento ( Opzionale, default = 10). |
SCROLL_WAIT_TIME | Se SCROLL_ACTION è USE_GESTURE , il tempo in millisecondi di attesa tra i movimenti di scorrimento durante la ricerca di un oggetto su cui fare clic. ( Facoltativo, predefinito = 1). |
SWIPE_CONFIG
Oggetto | Descrizione |
---|---|
SWIPE_DIRECTION | O TOP_TO_BOTTOM , BOTTOM_TO_TOP , LEFT_TO_RIGHT o RIGHT_TO_LEFT |
SWIPE_FRACTION | Uno dei seguenti:
|
NUMBER_OF_STEPS | Il numero di passaggi da utilizzare per eseguire lo scorrimento. Vedere segmentSteps . |
Costruisci ed esegui
Il framework Spectatio viene creato automaticamente come parte dell'APK di test. Per creare l'APK di test, la codebase AOSP deve risiedere sulla workstation locale. Dopo aver creato l'APK di test, l'utente deve installare l'APK sul dispositivo ed eseguire il test.
L'esempio di codice seguente mostra la creazione, l'installazione e l'esecuzione di un APK di test.
# 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
In questi comandi:
TEST-APK-NAME : il nome dell'app da testare. Ad esempio, imposta TEST-APK-NAME su
AndroidAutomotiveSettingsTests
per testare le impostazioni Wi-Fi come specificato nel fileAndroid.bp
. Il nome dell'APK si trova nel rispettivo fileAndroid.bp
per il test automobilistico .DEVICE-SERIAL : l'ID seriale del DUT. Questo parametro non è obbligatorio se all'host è connesso un solo dispositivo.
config-file-path
: parametro facoltativo richiesto solo per fornire configurazioni dell'interfaccia utente del dispositivo non predefinite come specificato nel file di configurazione JSON . Se non forniti, il framework utilizza valori predefiniti per l'esecuzione dei test.PATH-FOR-BUILT-TEST-APK : il percorso in cui viene creato l'APK di test quando viene eseguito il comando
make
.TEST-PACKAGE : il nome del pacchetto di test.
TEST-CLASSNAME : il nome della classe di test. Ad esempio, per il test delle impostazioni Wi-Fi , il pacchetto di test è
android.platform.tests
e il nome della classe di test èWifiSettingTest
.
Libreria di frammenti automobilistici
Automotive Snippet Library è un insieme di librerie di test Android per Android Open Source Project (AOSP) progettate per interagire con app e servizi automobilistici. Sfrutta Spectatio con un comodo meccanismo per eseguire chiamate di procedura remota (RPC) da una macchina host (test) a un dispositivo basato su Android.
Iniziare
Prima di iniziare, rivedi queste sezioni.
Prerequisiti
- Python 3.x installato sul computer host.
- Configurazione dell'ambiente AOSP con gli strumenti di creazione necessari.
- Un dispositivo automobilistico Android (emulatore o dispositivo fisico) con accesso adb.
Compilazione
Per compilare i vari snippet forniti dalla Automotive Snippet Library, puoi utilizzare il file android.bp
fornito. Seguire i comandi nella sezione precedente per compilare l'APK.
Distribuzione
Dopo aver compilato con successo le librerie di snippet, distribuisci gli APK risultanti sul dispositivo di destinazione utilizzando il comando adb install
menzionato nella sezione precedente.
Esegui dei test
Le librerie di snippet espongono diversi metodi RPC per interagire con il sistema automobilistico. Questi metodi possono essere richiamati tramite il framework Mobly dal computer host. Supponendo che tu abbia configurato l'ambiente di test Mobly, puoi utilizzare lo script snippet_shell.py
per aprire una shell Python interattiva, dove puoi richiamare manualmente i metodi RPC sul dispositivo. Invocazione di esempio:
python3 snippet_shell.py com.google.android.mobly.snippet.bundled -s <serial>
Sostituisci <serial>
con il numero di serie del dispositivo, che puoi ottenere con adb devices se sono collegati più dispositivi.
Librerie incluse
La libreria di snippet automobilistici include le seguenti librerie di snippet e helper:
AutomotiveSnippet: fornisce API relative alle operazioni del veicolo, come composizione, controllo del volume, tasti fisici del veicolo e interazione con il centro multimediale.
PhoneSnippet: fornisce API relative alla telefonia, inclusa la gestione delle chiamate, la navigazione dei contatti e le operazioni SMS.
Lo snippet Automotive e PhoneSnippet condividono una logica comune. Nello specifico, puoi invadere le chiamate RCP relative al Bluetooth per accoppiare un'auto e un dispositivo telefonico. Questo bt_discovery_test
mostra come.
- TEST-CLASSNAME : il nome della classe di test. Ad esempio, per il test delle impostazioni Wi-Fi , il pacchetto di test è
android.platform.tests
e il nome della classe di test èWifiSettingTest
.