Spectatio est un framework de test Open Source développé pour tester Android Automotive OS (AAOS) sur des appareils réels et virtuels. Spectatio fournit des API pour tester des applications sur un appareil automobile. Il s'agit d'une solution extensible et évolutive utilisée pour vérifier les capacités et les performances d'AAOS et de ses applications.
Conception de haut niveau
Le framework Spectatio est adaptable et extensible pour diverses implémentations d'UI AAOS. Il est utilisé pour tester les capacités et les performances d'AAOS sur le matériel de l'appareil, les émulateurs et les environnements virtualisés.
La figure suivante explique la conception générale du framework Spectatio.
Figure 1 : Conception générale du framework Spectatio.
Basé sur UI Automator, le framework Spectatio fournit un ensemble d'API permettant de créer des tests d'interface utilisateur qui interagissent avec les applications utilisateur et système sur AAOS. Les tests automobiles utilisent les API fournies par le framework Spectatio pour les tests, ce qui rend ces tests indépendants de l'appareil testé (DUT) et évolutifs pour tester différents appareils, si pris en charge.
La figure 1 montre que le framework Spectatio est modularisé en fonction des applications de référence telles que Dialer, Medicenter et Settings à l'aide d'interfaces et d'assistants spécifiques aux applications, ce qui le rend facilement extensible pour les nouvelles applications. Le framework Spectatio réutilise les classes d'assistance utilitaires et standards courantes. La classe d'assistance standard est la classe parente de toutes les fonctions d'assistance de l'application. Elle fournit des fonctions standards spécifiques à l'appareil ou applicables à toutes les applications. Les classes d'assistance utilitaires fournissent des utilitaires tels que la lecture ou l'écriture de fichiers à partir de l'appareil.
Architecture
Pour fournir un ensemble d'API permettant de créer des tests d'UI, le framework Spectatio implémente des interfaces et des assistants spécifiques à l'application tout en étendant la classe d'assistance standard existante et en important les classes d'assistance utilitaires.
La figure 2 illustre l'architecture de haut niveau du framework Spectatio et de toutes les entités impliquées dans l'implémentation des API pour tester une application.
Figure 2. Architecture de haut niveau du framework Spectatio.
L'interface d'application d'assistance fournit un plan pour l'implémentation d'une application d'assistance. Il se compose de diverses fonctions d'assistance nécessaires pour tester les applications. Chaque application possède sa propre interface, comme IAutoSettingHelper
et IAutoDialHelper
.
Pour en savoir plus et obtenir la liste des fonctions d'interface, consultez les fonctions d'interface de l'assistant d'application sur AOSP.
La classe d'assistance standard se compose d'attributs et de fonctions standards requis pour la configuration de l'appareil, mais qui ne sont spécifiques à aucune application, comme pressHome
et scroll
. La classe d'assistance standard est définie dans AbstractAutoStandardAppHelper.java
.
Le framework utilise les classes d'assistance utilitaires. Par exemple, AutoJsonUtility.java
est une classe utilitaire qui charge le fichier de configuration JSON de l'appareil donné et met à jour les configurations du framework au moment de l'exécution.
Le module d'implémentation de l'assistant d'application est au cœur du framework Spectatio. Il contient l'implémentation des fonctions d'assistance définies dans l'interface d'assistance de l'application, qui sont nécessaires pour tester les applications sur un appareil automobile. Chaque application possède sa propre implémentation, comme SettingHelperImpl
et DialHelperImpl
, utilisée par les tests Automotive pour tester les applications. Pour en savoir plus et obtenir la liste des implémentations, consultez les fonctions d'implémentation de l'application d'assistance sur AOSP.
Les tests automobiles utilisent les fonctions d'implémentation de l'assistant d'application pour tester diverses opérations liées à l'application. Utilisez la classe HelperAccessor
pour accéder aux fonctions d'implémentation de l'assistant d'application.
Le code suivant montre la configuration, le nettoyage et l'exécution d'un exemple de test automobile.
@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());
}
}
Personnalisation
Le framework Spectatio est indépendant de l'UI de l'appareil. Il est donc évolutif pour les appareils de test avec des UI et du matériel variés. Pour atteindre cette évolutivité, Spectatio utilise des configurations d'appareil par défaut basées sur l'appareil de référence. Pour prendre en charge les configurations d'appareil non définies par défaut, le framework utilise un fichier de configuration JSON au moment de l'exécution pour définir les modifications d'UI souhaitées pour l'appareil. Un fichier de configuration JSON est compatible avec les éléments d'interface utilisateur tels que TEXT
, DESCRIPTION
et RESOURCE_ID
, ainsi qu'avec les paramètres path
. Il ne doit contenir que les informations sur les modifications de l'interface utilisateur pour l'appareil en test. Les autres éléments de l'UI utilisent les valeurs de configuration par défaut fournies dans le framework.
Configurations d'appareil par défaut
L'exemple de fichier de configuration JSON suivant montre les configurations d'appareil disponibles et leurs valeurs par défaut.
Cliquez ici pour afficher un exemple de fichier de configuration JSON.
{ "SETTINGS": { "APPLICATION_CONFIG": { "SETTINGS_TITLE_TEXT": "Settings", "SETTINGS_PACKAGE": "com.android.car.settings", "SETTINGS_RRO_PACKAGE": "com.android.car.settings.googlecarui.rro", "OPEN_SETTINGS_COMMAND": "am start -a android.settings.SETTINGS", "OPEN_QUICK_SETTINGS_COMMAND": "am start -n com.android.car.settings/com.android.car.settings.common.CarSettingActivity" }, "QUICK_SETTINGS": { "OPEN_MORE_SETTINGS": { "TYPE": "RESOURCE_ID", "VALUE": "toolbar_menu_item_1", "PACKAGE": "com.android.car.settings" }, "NIGHT_MODE": { "TYPE": "TEXT", "VALUE": "Night mode" } }, "DISPLAY": { "PATH": "Settings > Display", "OPTIONS": [ "Brightness level" ], "BRIGHTNESS_LEVEL": { "TYPE": "RESOURCE_ID", "VALUE": "seekbar", "PACKAGE": "com.android.car.settings" } }, "SOUND": { "PATH": "Settings > Sound", "OPTIONS": [ "Media volume", "Alarm volume" ] }, "NETWORK_AND_INTERNET": { "PATH": "Settings > Network & internet", "OPTIONS": [ ], "TOGGLE_WIFI": { "TYPE": "RESOURCE_ID", "VALUE": "master_switch", "PACKAGE": "com.android.car.settings" } }, "BLUETOOTH": { "PATH": "Settings > Bluetooth", "OPTIONS": [ ], "TOGGLE_BLUETOOTH": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_menu_item_switch", "PACKAGE": "com.android.car.settings" } }, "APPS_AND_NOTIFICATIONS": { "PATH": "Settings > Apps & notifications", "OPTIONS": [ ], "SHOW_ALL_APPS": { "TYPE": "TEXT", "VALUE": "Show all apps" }, "ENABLE_DISABLE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_menu_item_text", "PACKAGE": "com.android.car.settings" }, "DISABLE_BUTTON_TEXT": { "TYPE": "TEXT", "VALUE": "Disable" }, "ENABLE_BUTTON_TEXT": { "TYPE": "TEXT", "VALUE": "Enable" }, "DISABLE_APP_BUTTON": { "TYPE": "TEXT", "VALUE": "DISABLE APP" }, "FORCE_STOP_BUTTON": { "TYPE": "TEXT", "VALUE": "Force stop" }, "OK_BUTTON": { "TYPE": "TEXT", "VALUE": "OK" }, "PERMISSIONS_MENU": { "TYPE": "TEXT", "VALUE": "Permissions" }, "ALLOW_BUTTON": { "TYPE": "TEXT", "VALUE": "Allow" }, "DENY_BUTTON": { "TYPE": "TEXT", "VALUE": "Deny" }, "DENY_ANYWAY_BUTTON": { "TYPE": "TEXT", "VALUE": "Deny anyway" } }, "DATE_AND_TIME": { "PATH": "Settings > Date & time", "OPTIONS": [ "Automatic date & time", "Automatic time zone" ], "AUTOMATIC_DATE_AND_TIME": { "TYPE": "TEXT", "VALUE": "Automatic date & time" }, "AUTOMATIC_TIME_ZONE": { "TYPE": "TEXT", "VALUE": "Automatic time zone" }, "SET_DATE": { "TYPE": "TEXT", "VALUE": "Set date" }, "SET_TIME": { "TYPE": "TEXT", "VALUE": "Set time" }, "SELECT_TIME_ZONE": { "TYPE": "TEXT", "VALUE": "Select time zone" }, "USE_24_HOUR_FORMAT": { "TYPE": "TEXT", "VALUE": "Use 24-hour format" }, "OK_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "toolbar_menu_item_0", "PACKAGE": "com.android.car.settings" }, "NUMBER_PICKER_WIDGET": { "TYPE": "CLASS", "VALUE": "android.widget.NumberPicker" }, "EDIT_TEXT_WIDGET": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" } }, "USERS": { "PATH": "Settings > Users", "OPTIONS": [ "Guest" ] }, "ACCOUNTS": { "PATH": "Settings > Accounts", "OPTIONS": [ "Automatically sync data" ], "ADD_ACCOUNT": { "TYPE": "TEXT", "VALUE": "ADD ACCOUNT" }, "ADD_GOOGLE_ACCOUNT": { "TYPE": "TEXT", "VALUE": "Google" }, "SIGN_IN_ON_CAR_SCREEN": { "TYPE": "TEXT", "VALUE": "Sign in on car screen" }, "GOOGLE_SIGN_IN_SCREEN": { "TYPE": "TEXT", "VALUE": "Sign in to your Google Account" }, "ENTER_EMAIL": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" }, "ENTER_PASSWORD": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" }, "NEXT_BUTTON": { "TYPE": "TEXT", "VALUE": "Next" }, "DONE_BUTTON": { "TYPE": "TEXT", "VALUE": "Done" }, "REMOVE_BUTTON": { "TYPE": "TEXT", "VALUE": "Remove" }, "REMOVE_ACCOUNT_BUTTON": { "TYPE": "TEXT", "VALUE": "Remove Account" } }, "SYSTEM": { "PATH": "Settings > System", "OPTIONS": [ "About", "Legal information" ], "ABOUT_MENU": { "TYPE": "TEXT", "VALUE": "About" }, "RESET_OPTIONS_MENU": { "TYPE": "TEXT", "VALUE": "Reset options" }, "LANGUAGES_AND_INPUT_MENU": { "TYPE": "TEXT", "VALUE": "Languages & input" }, "DEVICE_MODEL": { "TYPE": "TEXT", "VALUE": "Model" }, "ANDROID_VERSION": { "TYPE": "TEXT", "VALUE": "Android version" }, "ANDROID_SECURITY_PATCH_LEVEL": { "TYPE": "TEXT", "VALUE": "Android security patch level" }, "KERNEL_VERSION": { "TYPE": "TEXT", "VALUE": "Kernel version" }, "BUILD_NUMBER": { "TYPE": "TEXT", "VALUE": "Build number" }, "RECYCLER_VIEW_WIDGET": { "TYPE": "CLASS", "VALUE": "androidx.recyclerview.widget.RecyclerView" }, "RESET_NETWORK": { "TYPE": "TEXT", "VALUE": "Reset network" }, "RESET_SETTINGS": { "TYPE": "TEXT", "VALUE": "RESET SETTINGS" }, "RESET_APP_PREFERENCES": { "TYPE": "TEXT", "VALUE": "Reset app preferences" }, "RESET_APPS": { "TYPE": "TEXT", "VALUE": "RESET APPS" }, "LANGUAGES_MENU": { "TYPE": "TEXT", "VALUE": "Languages" }, "LANGUAGES_MENU_IN_SELECTED_LANGUAGE": { "TYPE": "TEXT", "VALUE": "Idiomas" } }, "SECURITY": { "PATH": "Settings > Security", "OPTIONS": [ ], "TITLE": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_title", "PACKAGE": "com.android.car.settings.googlecarui.rro" }, "CHOOSE_LOCK_TYPE": { "TYPE": "TEXT", "VALUE": "Choose a lock type" }, "LOCK_TYPE_PASSWORD": { "TYPE": "TEXT", "VALUE": "Password" }, "LOCK_TYPE_PIN": { "TYPE": "TEXT", "VALUE": "PIN" }, "LOCK_TYPE_NONE": { "TYPE": "TEXT", "VALUE": "None" }, "CONTINUE_BUTTON": { "TYPE": "TEXT", "VALUE": "Continue" }, "CONFIRM_BUTTON": { "TYPE": "TEXT", "VALUE": "Confirm" }, "ENTER_PASSWORD": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" }, "PIN_PAD": { "TYPE": "RESOURCE_ID", "VALUE": "pin_pad", "PACKAGE": "com.android.car.settings" }, "ENTER_PIN_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "key_enter", "PACKAGE": "com.android.car.settings" }, "REMOVE_BUTTON": { "TYPE": "TEXT", "VALUE": "Remove" } } }, "PHONE": { "APPLICATION_CONFIG": { "DIAL_PACKAGE": "com.android.car.dialer", "PHONE_ACTIVITY": "com.android.car.dialer/.ui.TelecomActivity", "OPEN_DIAL_PAD_COMMAND": "am start -a android.intent.action.DIAL" }, "IN_CALL_VIEW": { "DIALED_CONTACT_TITLE": { "TYPE": "RESOURCE_ID", "VALUE": "user_profile_title", "PACKAGE": "com.android.car.dialer" }, "DIALED_CONTACT_NUMBER": { "TYPE": "RESOURCE_ID", "VALUE": "user_profile_phone_number", "PACKAGE": "com.android.car.dialer" }, "END_CALL": { "TYPE": "RESOURCE_ID", "VALUE": "end_call_button", "PACKAGE": "com.android.car.dialer" }, "MUTE_CALL": { "TYPE": "RESOURCE_ID", "VALUE": "mute_button", "PACKAGE": "com.android.car.dialer" }, "SWITCH_TO_DIAL_PAD": { "TYPE": "RESOURCE_ID", "VALUE": "toggle_dialpad_button", "PACKAGE": "com.android.car.dialer" }, "CHANGE_VOICE_CHANNEL": { "TYPE": "RESOURCE_ID", "VALUE": "voice_channel_view", "PACKAGE": "com.android.car.dialer" }, "VOICE_CHANNEL_CAR": { "TYPE": "TEXT", "VALUE": "Car speakers" }, "VOICE_CHANNEL_PHONE": { "TYPE": "TEXT", "VALUE": "Phone" } }, "DIAL_PAD_VIEW": { "DIAL_PAD_MENU": { "TYPE": "TEXT", "VALUE": "Dial Pad" }, "DIAL_PAD_FRAGMENT": { "TYPE": "RESOURCE_ID", "VALUE": "dialpad_fragment", "PACKAGE": "com.android.car.dialer" }, "DIALED_NUMBER": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.dialer" }, "MAKE_CALL": { "TYPE": "RESOURCE_ID", "VALUE": "call_button", "PACKAGE": "com.android.car.dialer" }, "DELETE_NUMBER": { "TYPE": "RESOURCE_ID", "VALUE": "delete_button", "PACKAGE": "com.android.car.dialer" } }, "CONTACTS_VIEW": { "CONTACTS_MENU": { "TYPE": "TEXT", "VALUE": "Contacts" }, "CONTACT_INFO": { "TYPE": "RESOURCE_ID", "VALUE": "call_action_id", "PACKAGE": "com.android.car.dialer" }, "CONTACT_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.dialer" }, "CONTACT_DETAIL": { "TYPE": "RESOURCE_ID", "VALUE": "show_contact_detail_id", "PACKAGE": "com.android.car.dialer" }, "ADD_CONTACT_TO_FAVORITE": { "TYPE": "RESOURCE_ID", "VALUE": "contact_details_favorite_button", "PACKAGE": "com.android.car.dialer" }, "SEARCH_CONTACT": { "TYPE": "RESOURCE_ID", "VALUE": "menu_item_search", "PACKAGE": "com.android.car.dialer" }, "CONTACT_SEARCH_BAR": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_search_bar", "PACKAGE": "com.android.car.dialer" }, "SEARCH_RESULT": { "TYPE": "RESOURCE_ID", "VALUE": "contact_name", "PACKAGE": "com.android.car.dialer" }, "CONTACT_SETTINGS": { "TYPE": "RESOURCE_ID", "VALUE": "menu_item_setting", "PACKAGE": "com.android.car.dialer" }, "CONTACT_ORDER": { "TYPE": "TEXT", "VALUE": "Contact order" }, "SORT_BY_FIRST_NAME": { "TYPE": "TEXT", "VALUE": "First name" }, "SORT_BY_LAST_NAME": { "TYPE": "TEXT", "VALUE": "Last Name" }, "CONTACT_TYPE_WORK": { "TYPE": "TEXT", "VALUE": "Work" }, "CONTACT_TYPE_MOBILE": { "TYPE": "TEXT", "VALUE": "Mobile" }, "CONTACT_TYPE_HOME": { "TYPE": "TEXT", "VALUE": "Home" } }, "CALL_HISTORY_VIEW": { "CALL_HISTORY_MENU": { "TYPE": "TEXT", "VALUE": "Recents" }, "CALL_HISTORY_INFO": { "TYPE": "RESOURCE_ID", "VALUE": "call_action_id", "PACKAGE": "com.android.car.dialer" } }, "FAVORITES_VIEW": { "FAVORITES_MENU": { "TYPE": "TEXT", "VALUE": "Favorites" } } }, "NOTIFICATIONS": { "APPLICATION_CONFIG": { "OPEN_NOTIFICATIONS_COMMAND": "service call statusbar 1" }, "EXPANDED_NOTIFICATIONS_SCREEN": { "NOTIFICATION_VIEW": { "TYPE": "RESOURCE_ID", "VALUE": "notification_view", "PACKAGE": "com.android.systemui" }, "CLEAR_ALL_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "clear_all_button", "PACKAGE": "com.android.systemui" }, "STATUS_BAR": { "TYPE": "RESOURCE_ID", "VALUE": "car_top_navigation_bar_container", "PACKAGE": "com.android.systemui" }, "APP_ICON": { "TYPE": "RESOURCE_ID", "VALUE": "app_icon", "PACKAGE": "com.android.systemui" }, "APP_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "header_text", "PACKAGE": "com.android.systemui" }, "NOTIFICATION_TITLE": { "TYPE": "RESOURCE_ID", "VALUE": "notification_body_title", "PACKAGE": "com.android.systemui" }, "NOTIFICATION_BODY": { "TYPE": "RESOURCE_ID", "VALUE": "notification_body_content", "PACKAGE": "com.android.systemui" }, "CARD_VIEW": { "TYPE": "RESOURCE_ID", "VALUE": "card_view", "PACKAGE": "com.android.systemui" } } }, "MEDIA_CENTER": { "APPLICATION_CONFIG": { "MEDIA_CENTER_PACKAGE": "com.android.car.media", "MEDIA_ACTIVITY": "com.android.bluetooth/com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService" }, "MEDIA_CENTER_SCREEN": { "PLAY_PAUSE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "play_pause_stop", "PACKAGE": "com.android.car.media" }, "NEXT_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_next", "PACKAGE": "com.android.car.media" }, "PREVIOUS_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_prev", "PACKAGE": "com.android.car.media" }, "SHUFFLE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "overflow_on", "PACKAGE": "com.android.car.media" }, "PLAY_QUEUE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "play_queue", "PACKAGE": "com.android.car.media" }, "MINIMIZED_MEDIA_CONTROLS": { "TYPE": "RESOURCE_ID", "VALUE": "minimized_playback_controls", "PACKAGE": "com.android.car.media" }, "TRACK_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.media" }, "TRACK_NAME_MINIMIZED_CONTROL": { "TYPE": "RESOURCE_ID", "VALUE": "minimized_control_bar_title", "PACKAGE": "com.android.car.media" }, "BACK_BUTTON": { "TYPE": "DESCRIPTION", "VALUE": "Back" } }, "MEDIA_CENTER_ON_HOME_SCREEN": { "PLAY_PAUSE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "play_pause_stop", "PACKAGE": "com.android.car.carlauncher" }, "NEXT_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_next", "PACKAGE": "com.android.car.carlauncher" }, "PREVIOUS_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_prev", "PACKAGE": "com.android.car.carlauncher" }, "TRACK_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.carlauncher" } } } }
Configurations alternatives des appareils
L'exemple de code suivant montre un exemple de fichier de configuration JSON dans lequel les paramètres par défaut sont remplacés par les paramètres du DUT. Dans cet exemple :
Les paramètres Internet sont nommés Réseau et Internet sur les appareils de référence et Connectivité sur l'appareil testé.
Les paramètres de date et d'heure sont disponibles sous Paramètres > Date et heure pour les appareils de référence et sous Paramètres > Système > Date et heure pour l'appareil en test.
// 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"
},
....
}
Lorsque le fichier de configuration JSON est prêt, il est fourni au moment de l'exécution, comme indiqué dans le bloc de code suivant :
# Push The JSON configuration file to the device
adb -s DEVICE-SERIAL push PATH-OF-JSON-FILE /data/local/tmp/runtimeSpectatioConfig.json
Dans cette commande :
DEVICE-SERIAL : ID de série du DUT. Ce paramètre n'est pas obligatoire si un seul appareil est connecté à l'hôte.
PATH-TO-JSON-FILE : chemin d'accès au fichier JSON sur la machine hôte.
Format de configuration
La configuration comporte cinq objets de premier niveau, avec les clés et valeurs suivantes :
Objet | Description |
---|---|
PACKAGES |
Objet décrivant le package principal de différentes applications, qui sont utilisées pour déterminer quand cette application est au premier plan. |
ACTIONS |
Objet indiquant les types d'actions et les paramètres pour différentes actions. Par exemple, si vous souhaitez utiliser des boutons ou un geste pour faire défiler l'écran. |
COMMANDS |
Objet spécifiant les commandes qui effectuent diverses actions. |
UI_ELEMENTS |
Objet utilisé pour construire des `BySelectors` UI Automator qui sélectionnent des éléments d'interface utilisateur (décrits en détail ci-dessous). |
WORKFLOWS |
Séquences d'actions permettant d'accomplir des tâches de haut niveau (décrites en détail ci-dessous). |
Éléments d'interface utilisateur
Chaque élément d'interface utilisateur possède un TYPE
qui spécifie ce que UI Automator recherchera pour identifier l'élément (comme l'ID de ressource, le texte et la description) et les valeurs de configuration associées à ce type. En général, chaque fois qu'un assistant identifie un élément à l'écran à l'aide de cette configuration, il obtient exactement un élément. Si plusieurs éléments correspondent à la configuration, l'un d'eux est utilisé de manière arbitraire dans le test. Par conséquent, la configuration doit (généralement) être suffisamment spécifique pour se limiter à un seul élément dans le contexte concerné.
TEXTE
Il s'agit du type d'élément d'UI le plus simple. L'élément d'interface utilisateur est identifié par son texte et nécessite une correspondance exacte.
"CALL_HISTORY_MENU": {
"TYPE": "TEXT",
"VALUE": "Recents"
}
TEXT_CONTAINS
Identique à TEXT
, sauf que le VALUE
spécifié n'a besoin d'apparaître que quelque part dans le texte de l'élément à faire correspondre.
"PRIVACY_CALENDAR": {
"TYPE": "TEXT_CONTAINS",
"VALUE": "Calendar"
}
DESCRIPTION
Identifiez l'élément par son attribut de description du contenu, qui doit correspondre exactement.
"APP_GRID_SCROLL_BACKWARD_BUTTON": {
"TYPE": "DESCRIPTION",
"VALUE": "Scroll up"
}
RESOURCE_ID
Identifiez l'élément par son ID de ressource, en vérifiant éventuellement également le composant de package de cet ID. La clé PACKAGE
est facultative. Si elle est omise, n'importe quel package correspondra, et seule la partie de l'ID suivant :id/
sera prise en compte.
"APP_LIST_SCROLL_ELEMENT": {
"TYPE": "RESOURCE_ID",
"VALUE": "apps_grid",
"PACKAGE": "com.android.car.carlauncher"
}
CLIQUABLE, DÉFILABLE
Identifiez l'élément en fonction de sa capacité à être cliqué ou à être défilé.
Il s'agit de types d'éléments très généraux, qui ne doivent généralement être utilisés dans un MULTIPLE
que pour affiner un autre type d'élément. La clé FLAG
est facultative et sa valeur par défaut est true
.
"SAMPLE_ELEMENT": {
"TYPE": "CLICKABLE",
"FLAG": false
}
CLASS
Identifiez l'élément en fonction de sa classe.
"SECURITY_SETTINGS_ENTER_PASSWORD": {
"TYPE": "CLASS",
"VALUE": "android.widget.EditText"
}
HAS_ANCESTOR
Identifiez l'élément en recherchant la hiérarchie des widgets au niveau de ses ancêtres. La clé ANCESTOR
contient un objet qui identifie l'ancêtre. La clé DEPTH
indique le niveau de la hiérarchie à examiner. DEPTH
est facultatif et a pour valeur par défaut 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_ANCESTOR",
"DEPTH": 2,
"ANCESTOR": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
HAS_DESCENDANT
Identifiez l'élément en examinant ses enfants dans la hiérarchie. La clé DESCENDANT
contient un objet qui spécifie l'enfant à rechercher. La clé DEPTH
spécifie le niveau de la hiérarchie à examiner. DEPTH
est facultatif et sa valeur par défaut est 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_DESCENDANT",
"DEPTH": 2,
"DESCENDANT": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
MULTIPLE
Identifiez l'élément en fonction de plusieurs conditions simultanées, qui doivent toutes être remplies.
"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"
}
}
]
}
Dans cet exemple, la configuration identifie un RelativeLayout
qui a un descendant à la profondeur 2
, dont le texte est Permission manager
.
Workflows
Un workflow représente une séquence d'actions utilisées pour accomplir une tâche particulière. Il peut différer suffisamment d'un type d'appareil à l'autre et est plus flexible à représenter dans la configuration que dans le code.
"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"
}
}
}
]
}
Chaque workflow est une paire clé/valeur où la clé correspond au nom du workflow et la valeur à un tableau d'actions à effectuer. Chaque action comporte un NAME
, un TYPE
, (généralement) un CONFIG
et (parfois) un SWIPE_CONFIG
ou un SCROLL_CONFIG
. Pour la plupart des TYPE, CONFIG
est un objet avec une clé UI_ELEMENT
dont la valeur prend la même forme qu'une entrée d'élément d'interface utilisateur (voir ci-dessus). Voici les types :
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 |
Pour les autres TYPE, voici les détails de configuration :
Objet | Description |
---|---|
COMMAND |
Objet avec une valeur TEXT contenant la commande à exécuter. |
HAS_PACKAGE_IN_FOREGROUND |
Objet avec une valeur TEXT contenant le package. |
SWIPE |
Omettez CONFIG key pour une action SWIPE . Cette expérience n'utilise que SWIPE_CONFIG . |
WAIT_MS |
Objet avec une valeur TEXT contenant le nombre de millisecondes à attendre. |
Les actions liées au défilement et au balayage nécessitent une configuration supplémentaire, comme suit :
SCROLL_CONFIG
Objet | Description |
---|---|
SCROLL_ACTION |
USE_GESTURE ou USE_BUTTON |
SCROLL_DIRECTION |
HORIZONTAL ou VERTICAL |
SCROLL_ELEMENT |
Objet indiquant le conteneur à faire défiler, en utilisant la même forme qu'une configuration d'élément d'UI (voir ci-dessus). |
SCROLL_FORWARD , SCROLL_BACKWARD |
Boutons de défilement vers l'avant et vers l'arrière (obligatoires lorsque SCROLL_ACTION est défini sur USE_BUTTON ). |
SCROLL_MARGIN |
Si SCROLL_ACTION est USE_GESTURE , la distance entre le bord du conteneur et le début et la fin du déplacement qui sera utilisé pour effectuer le défilement (facultatif,valeur par défaut : 10). |
SCROLL_WAIT_TIME |
Si SCROLL_ACTION est défini sur USE_GESTURE , il s'agit du temps en millisecondes à attendre entre les gestes de défilement lors de la recherche d'un objet sur lequel cliquer.
(Facultatif,valeur par défaut : 1). |
SWIPE_CONFIG
Objet | Description |
---|---|
SWIPE_DIRECTION |
TOP_TO_BOTTOM , BOTTOM_TO_TOP , LEFT_TO_RIGHT ou RIGHT_TO_LEFT |
SWIPE_FRACTION |
L'un des éléments suivants :
|
NUMBER_OF_STEPS |
Nombre d'étapes à utiliser pour effectuer le balayage. Consultez la
segmentSteps .
|
Compiler et exécuter
Le framework Spectatio est automatiquement créé dans l'APK de test. Pour créer l'APK de test, le codebase AOSP doit résider sur le poste de travail local. Une fois l'APK de test créé, l'utilisateur doit l'installer sur l'appareil et exécuter le test.
L'exemple de code suivant montre la création, l'installation et l'exécution d'un APK de 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
Dans ces commandes :
TEST-APK-NAME : nom de l'application à tester. Par exemple, définissez TEST-APK-NAME sur
AndroidAutomotiveSettingsTests
pour tester les paramètres Wi-Fi spécifiés dans le fichierAndroid.bp
. Le nom de l'APK se trouve dans le fichierAndroid.bp
correspondant au test automobile.DEVICE-SERIAL : ID de série du DUT. Ce paramètre n'est pas obligatoire si un seul appareil est connecté à l'hôte.
config-file-path
: paramètre facultatif qui n'est requis que pour fournir des configurations d'interface utilisateur d'appareil non définies par défaut, comme spécifié dans le fichier de configuration JSON. Si aucune valeur n'est fournie, le framework utilise des valeurs par défaut pour exécuter les tests.PATH-FOR-BUILT-TEST-APK : chemin d'accès où l'APK de test est créé lorsque la commande
make
est exécutée.TEST-PACKAGE : nom du package de test.
TEST-CLASSNAME : nom de la classe de test. Par exemple, pour le test Paramètres Wi-Fi, le package de test est
android.platform.tests
et le nom de la classe de test estWifiSettingTest
.
Bibliothèque d'extraits pour l'automobile
La bibliothèque d'extraits Automotive est un ensemble de bibliothèques de test Android pour le projet Android Open Source (AOSP) conçu pour interagir avec les applications et services automobiles. Il utilise Spectatio avec un mécanisme pratique pour exécuter des appels de procédure à distance (RPC) à partir d'une machine hôte (de test) vers un appareil Android.
Premiers pas
Avant de commencer, consultez ces sections.
Prérequis
- Python 3.x est installé sur la machine hôte.
- Configuration de l'environnement AOSP avec les outils de compilation nécessaires.
- Un appareil Android Automotive (émulateur ou appareil physique) avec accès adb.
Compilation
Pour compiler les différents extraits fournis par la bibliothèque d'extraits Automotive, vous pouvez utiliser le fichier android.bp
fourni. Suivez les commandes de la section précédente pour compiler l'APK.
Déploiement
Une fois les bibliothèques d'extraits compilées, déployez les APK obtenus sur l'appareil cible à l'aide de la commande adb install
mentionnée dans la section précédente.
Exécuter des tests
Les bibliothèques d'extraits de code exposent plusieurs méthodes RPC permettant d'interagir avec le système automobile. Ces méthodes peuvent être appelées via le framework Mobly à partir de la machine hôte. En supposant que vous ayez configuré l'environnement de test Mobly, vous pouvez utiliser le script snippet_shell.py
pour ouvrir un shell Python interactif, dans lequel vous pouvez appeler manuellement des méthodes RPC sur l'appareil. Exemple d'appel :
python3 snippet_shell.py com.google.android.mobly.snippet.bundled -s <serial>
Remplacez <serial>
par le numéro de série de l'appareil, que vous pouvez obtenir avec adb devices si plusieurs appareils sont connectés.
Bibliothèques incluses
La bibliothèque d'extraits Automotive inclut les bibliothèques d'extraits et les assistants suivants :
AutomotiveSnippet : fournit des API liées aux opérations du véhicule, telles que la numérotation, le contrôle du volume, les touches physiques du véhicule et l'interaction avec le centre multimédia.
PhoneSnippet : fournit des API liées à la téléphonie, y compris la gestion des appels, la navigation dans les contacts et les opérations SMS.
Les extraits "Automobile" et "Numéro de téléphone" partagent une logique commune.
Plus précisément, vous pouvez envahir les appels RCP liés au Bluetooth pour associer un appareil automobile et un téléphone. Ce bt_discovery_test
vous explique comment procéder.
- TEST-CLASSNAME : nom de la classe de test. Par exemple, pour le test Paramètres Wi-Fi, le package de test est
android.platform.tests
et le nom de la classe de test estWifiSettingTest
.