Spectatio è un framework di test open source sviluppato per testare Android Automotive OS (AAOS) su dispositivi reali e virtuali. Spectatio fornisce API per testare le app su un dispositivo per auto ed è una soluzione estendibile e scalabile utilizzata per verificare la funzionalità e il rendimento di AAOS e delle relative app.
Progettazione di alto livello
Il framework Spectatio è adattabile ed espandibile per varie implementazioni dell'interfaccia utente di AAOS. Viene utilizzato per testare la funzionalità e il rendimento di AAOS su hardware del dispositivo, emulatori e ambienti virtualizzati.
La figura seguente illustra la progettazione di alto livello del framework Spectatio.
Figura 1. Progettazione di alto livello del framework Spectatio.
Basato su UI Automator, il framework Spectatio fornisce un insieme di API per creare test dell'interfaccia utente che interagiscono con le app utente e di sistema su AAOS. I test per auto utilizzano le API fornite dal framework Spectatio per i test, il che rende questi test indipendenti dal dispositivo in fase di test (DUT) e scalabili per testare vari dispositivi, se supportati.
La Figura 1 mostra che il framework Spectatio è modularizzato in base alle app di riferimento come Dialer, Medicenter e Impostazioni utilizzando interfacce e helper specifici dell'app, il che lo rende facilmente estendibile per le nuove app. Il framework Spectatio riutilizza le classi helper standard e 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 un insieme 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 helper dell'app fornisce un progetto per l'implementazione di un helper dell'app. È costituita da varie funzioni helper 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, consulta le funzioni dell'interfaccia helper dell'app su AOSP.
La classe helper standard è costituita da attributi e funzioni standard necessari per la configurazione del dispositivo, ma non specifici di 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 cuore del framework Spectatio. Contiene l'implementazione delle funzioni helper definite nell'interfaccia helper dell'app, necessarie per testare le app su un dispositivo per auto. Ogni app ha la propria implementazione, ad esempio SettingHelperImpl
e
DialHelperImpl,
utilizzate dai
test per auto per testare le app. Per ulteriori informazioni e un elenco delle
implementazioni, consulta le funzioni di implementazione dell'helper dell'app
'su AOSP.
I test per auto
utilizzano le funzioni di implementazione dell'helper dell'app per testare varie operazioni
correlate all'app. Utilizza la classe HelperAccessor
per accedere alle funzioni di implementazione dell'helper dell'app.
Il seguente codice mostra la configurazione, la pulizia e l'esecuzione di un test per auto 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 le configurazioni predefinite del dispositivo in base al dispositivo di riferimento. Per supportare le configurazioni dei dispositivi non predefinite, il framework utilizza un file di configurazione JSON in fase di runtime per impostare le modifiche dell'interfaccia utente desiderate 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 utilizza 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.
Fai 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
Il seguente esempio di codice mostra un esempio del file di configurazione JSON in cui le impostazioni predefinite vengono sostituite dalle impostazioni del 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 runtime 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 al computer host è collegato un solo dispositivo.
PATH-TO-JSON-FILE: percorso del file JSON sulla macchina host.
Formato 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 pulsanti o un gesto per scorrere. |
COMMANDS |
Un oggetto che specifica i comandi che eseguono varie azioni. |
UI_ELEMENTS |
Un oggetto utilizzato per creare `BySelectors` di UI Automator che selezionano gli elementi dell'interfaccia utente (descritti in dettaglio di seguito). |
WORKFLOWS |
Sequenze di azioni che eseguono attività di alto livello (descritte 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 (ad esempio 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, ne viene utilizzato uno arbitrario nel test. Pertanto, la configurazione deve (in genere) essere scritta in modo sufficientemente specifico da restringere a un elemento nel contesto pertinente.
TEXT
Questo è il tipo di elemento dell'interfaccia utente più semplice. L'elemento dell'interfaccia utente viene identificato dal relativo testo e richiede una corrispondenza esatta.
"CALL_HISTORY_MENU": {
"TYPE": "TEXT",
"VALUE": "Recents"
}
TEXT_CONTAINS
Uguale a TEXT, tranne per il fatto che il VALUE specificato deve essere presente solo da qualche parte nel testo dell'elemento per essere abbinato.
"PRIVACY_CALENDAR": {
"TYPE": "TEXT_CONTAINS",
"VALUE": "Calendar"
}
DESCRIPTION
Identifica l'elemento in base al relativo attributo di descrizione dei contenuti, che richiede una corrispondenza esatta.
"APP_GRID_SCROLL_BACKWARD_BUTTON": {
"TYPE": "DESCRIPTION",
"VALUE": "Scroll up"
}
RESOURCE_ID
Identifica l'elemento in base al relativo ID risorsa, controllando facoltativamente anche il componente del pacchetto di questo ID. La chiave PACKAGE è facoltativa; se omessa, verrà abbinato qualsiasi pacchetto 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"
}
CLICKABLE, SCROLLABLE
Identifica l'elemento in base al fatto che sia (o meno) cliccabile o scorrevole.
Si tratta di tipi di elementi molto ampi e in genere devono essere utilizzati solo in un MULTIPLE per restringere un altro tipo di elemento. La chiave FLAG è facoltativa e il valore predefinito è true.
"SAMPLE_ELEMENT": {
"TYPE": "CLICKABLE",
"FLAG": false
}
CLASS
Identifica l'elemento in base alla relativa classe.
"SECURITY_SETTINGS_ENTER_PASSWORD": {
"TYPE": "CLASS",
"VALUE": "android.widget.EditText"
}
HAS_ANCESTOR
Identifica l'elemento cercando la gerarchia dei widget nei relativi antenati. La chiave ANCESTOR contiene un oggetto che identifica il predecessore. La chiave DEPTH specifica la profondità della gerarchia da cercare. DEPTH è facoltativo e ha un valore predefinito di 1.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_ANCESTOR",
"DEPTH": 2,
"ANCESTOR": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
HAS_DESCENDANT
Identifica l'elemento cercando nella gerarchia i relativi elementi secondari. La chiave DESCENDANT contiene un oggetto che specifica l'elemento secondario da cercare. La chiave DEPTH specifica la profondità della gerarchia da cercare. DEPTH è facoltativo e ha un valore predefinito di 1.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_DESCENDANT",
"DEPTH": 2,
"DESCENDANT": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
MULTIPLE
Identifica l'elemento in base a più condizioni simultanee, tutte le quali devono essere 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 elemento secondario con profondità 2, il cui testo è Permission manager.
Workflow
Un workflow rappresenta una sequenza di azioni utilizzate per eseguire una determinata attività, che può variare a sufficienza da un tipo di dispositivo all'altro 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 workflow è una coppia chiave-valore in cui la chiave è il nome del workflow e il valore è un array di azioni da eseguire. Ogni azione ha un NAME, un TYPE,
(in genere) 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 dell'interfaccia utente (vedi sopra). Questi TYPE sono:
| 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 |
Per gli altri TYPE, 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 |
Ometti il CONFIG key per un'azione SWIPE. Viene
utilizzato solo SWIPE_CONFIG |
WAIT_MS |
Un oggetto con un valore TEXT contenente il numero di
millisecondi da attendere. |
Le azioni correlate a scorrimento e scorrimento rapido richiedono una configurazione aggiuntiva, come segue:
SCROLL_CONFIG
| Oggetto | Descrizione |
|---|---|
SCROLL_ACTION |
USE_GESTURE o USE_BUTTON |
SCROLL_DIRECTION |
HORIZONTAL o VERTICAL |
SCROLL_ELEMENT |
Un oggetto che indica il container da scorrere, utilizzando la stessa forma di una configurazione di elementi dell'interfaccia utente (vedi sopra). |
SCROLL_FORWARD, SCROLL_BACKWARD |
I pulsanti di scorrimento in avanti e indietro (obbligatori quando
SCROLL_ACTION è USE_BUTTON). |
SCROLL_MARGIN |
Se SCROLL_ACTION è USE_GESTURE, la distanza
dal bordo del container per avviare e interrompere il trascinamento che verrà utilizzato
per eseguire lo scorrimento (facoltativo, valore predefinito = 10). |
SCROLL_WAIT_TIME |
Se SCROLL_ACTION è USE_GESTURE, il tempo in
millisecondi da attendere tra i gesti di scorrimento durante la ricerca di un oggetto su cui fare
clic.
(facoltativo, valore predefinito = 1). |
SWIPE_CONFIG
| Oggetto | Descrizione |
|---|---|
SWIPE_DIRECTION |
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 rapido. Vedi
segmentSteps.
|
Creazione ed esecuzione
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 installarlo sul dispositivo ed eseguire il test.
Il seguente esempio di codice 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
AndroidAutomotiveSettingsTestsper testare le impostazioni Wi-Fi come specificato nelAndroid.bpfile. Il nome dell'APK è riportato nel rispettivoAndroid.bpfile per il test per auto.DEVICE-SERIAL: l'ID seriale del DUT. Questo parametro non è obbligatorio se al computer host è collegato un solo dispositivo.
config-file-path: parametro facoltativo necessario solo per fornire configurazioni dell'interfaccia utente del dispositivo non predefinite come specificato nel file di configurazione JSON. Se non viene fornito, il framework utilizza i 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.testse il nome della classe di test èWifiSettingTest.
Raccolta di snippet per auto
La raccolta di snippet per auto è un insieme di librerie di test Android per l'Android Open Source Project (AOSP) progettate per interagire con app e servizi per auto. Sfrutta Spectatio con un meccanismo pratico per eseguire chiamate di procedure remote (RPC) da un computer host (di test) a un dispositivo con Android.
Inizia
Prima di iniziare, esamina queste sezioni.
Prerequisiti
- Python 3.x installato sulla macchina host.
- Configurazione dell'ambiente AOSP con gli strumenti di build necessari.
- Un dispositivo per auto Android (emulatore o dispositivo fisico) con accesso adb.
Compilation
Per compilare i vari snippet forniti dalla raccolta di snippet per auto, puoi utilizzare il file android.bp fornito. Segui i comandi nella sezione precedente per compilare l'APK.
Deployment
Dopo aver compilato correttamente le librerie di snippet, esegui il deployment degli APK risultanti sul dispositivo di destinazione utilizzando il comando adb install menzionato nella sezione precedente.
Esegui test
Le librerie di snippet espongono diversi metodi RPC per interagire con il sistema per auto. 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
snippet_shell.py script per aprire una shell Python interattiva, in cui puoi
richiamare manualmente i metodi RPC sul dispositivo. Esempio di chiamata:
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 raccolta di snippet per auto include le seguenti librerie e helper di snippet:
AutomotiveSnippet: fornisce API correlate alle operazioni del veicolo, come la composizione, il controllo del volume, i tasti fisici del veicolo e l'interazione con il centro multimediale.
PhoneSnippet: fornisce API correlate alla telefonia, tra cui la gestione delle chiamate, la navigazione tra i contatti e le operazioni SMS.
Lo snippet per auto e PhoneSnippet condividono una logica comune.
In particolare, puoi invadere le chiamate RCP correlate al Bluetooth per accoppiare un dispositivo per auto e un telefono. Questo bt_discovery_test mostra come fare.
- TEST-CLASSNAME: il nome della classe di test. Ad esempio, per il
test delle impostazioni Wi-Fi,
il pacchetto di test è
android.platform.testse il nome della classe di test èWifiSettingTest.