Spectatio: Test-Framework für die Automobilbranche

Spectatio ist ein Open-Source-Testframework, das für das Testen von Android Automotive OS (AAOS) auf echten und virtuellen Geräten entwickelt wurde. Spectatio bietet APIs zum Testen von Apps auf einem Fahrzeuggerät. Es ist eine erweiterbare und skalierbare Lösung, mit der die Funktionen und die Leistung von AAOS und seiner Apps überprüft werden.

Übergeordnetes Design

Das Spectatio-Framework ist anpassbar und erweiterbar für verschiedene AAOS-UI-Implementierungen. Es wird verwendet, um die Funktionen und die Leistung von AAOS auf Gerätehardware, Emulatoren und virtualisierten Umgebungen zu testen.

Die folgende Abbildung veranschaulicht das allgemeine Design des Spectatio-Frameworks.

Hochrangiges Design des Spectatio-Frameworks

Abbildung 1. Hochwertiges Design des Spectatio-Frameworks

Das Spectatio-Framework basiert auf UI Automator und bietet eine Reihe von APIs zum Erstellen von UI-Tests, die mit Nutzer- und System-Apps auf AAOS interagieren. Für Tests im Bereich Automotive werden die APIs des Spectatio-Frameworks verwendet. Dadurch sind diese Tests unabhängig vom Testgerät und skalierbar, um verschiedene Geräte zu testen, sofern unterstützt.

Abbildung 1 zeigt, dass das Spectatio-Framework auf der Grundlage von Referenz-Apps wie „Telefon“, „Medicenter“ und „Einstellungen“ mithilfe von app-spezifischen Oberflächen und Helfern modularisiert ist. Dadurch lässt es sich leicht für neue Apps erweitern. Das Spectatio-Framework verwendet die gängigen Standard- und Dienstprogramm-Hilfsklassen wieder. Die Standard-Hilfsklasse ist die übergeordnete Klasse für alle App-Hilfsfunktionen und bietet Standardfunktionen, die gerätespezifisch sind oder anwendungsübergreifend anwendbar sind. Die Hilfsklassen für Dienstprogramme bieten Dienstprogramme wie das Lesen oder Schreiben von Dateien auf dem Gerät.

Architektur

Um eine Reihe von APIs zum Erstellen von UI-Tests bereitzustellen, implementiert das Spectatio-Framework app-spezifische Schnittstellen und Helfer, erweitert die vorhandene Standard-Hilfeklasse und importiert die Dienstprogramm-Hilfeklassen.

In Abbildung 2 sehen Sie die allgemeine Architektur des Spectatio-Frameworks und alle Entitäten, die an der Implementierung von APIs zum Testen einer Anwendung beteiligt sind.

Gesamtarchitektur des Spectatio-Frameworks

Abbildung 2: Gesamtarchitektur des Spectatio-Frameworks

Die App-Hilfsoberfläche enthält eine Vorlage für die Implementierung eines App-Hilfsprogramms. Es enthält verschiedene Hilfsfunktionen, die zum Testen von Apps erforderlich sind. Jede App hat eine eigene Benutzeroberfläche, z. B. IAutoSettingHelper und IAutoDialHelper. Weitere Informationen und eine Liste der Schnittstellenfunktionen finden Sie in AOSP unter App Helper Interface Functions (App-Hilfsfunktionen für die Benutzeroberfläche).

Die Standard-Hilfsklasse besteht aus Standardattributen und ‑funktionen, die für die Geräteeinrichtung erforderlich sind, aber nicht für eine bestimmte App spezifisch sind, z. B. pressHome und scroll. Die Standard-Hilfsklasse ist in AbstractAutoStandardAppHelper.java definiert.

Die Hilfsklassen werden vom Framework verwendet. AutoJsonUtility.java ist beispielsweise eine Dienstprogrammklasse, die die angegebene JSON-Konfigurationsdatei des Geräts lädt und die Framework-Konfigurationen zur Laufzeit aktualisiert.

Das App Helper-Implementierungsmodul ist der Kern des Spectatio-Frameworks. Es enthält die Implementierung der in der App-Hilfsschnittstelle definierten Hilfsfunktionen, die zum Testen von Apps auf einem Automobilgerät erforderlich sind. Jede App hat eine eigene Implementierung, z. B. SettingHelperImpl und DialHelperImpl, die für die Tests der Apps verwendet werden. Weitere Informationen und eine Liste der Implementierungen finden Sie in AOSP unter App-Hilfe-Implementierungsfunktionen.

Bei Automotive-Tests werden die Implementierungsfunktionen des App-Hilfsprogramms verwendet, um verschiedene Vorgänge im Zusammenhang mit der App zu testen. Verwenden Sie die Klasse HelperAccessor, um Zugriff auf die Implementierungsfunktionen des App-Hilfsprogramms zu erhalten.

Der folgende Code zeigt die Einrichtung, Bereinigung und Ausführung eines Beispieltests für die Automobilbranche.

@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());
  }
}

Personalisierung

Das Spectatio-Framework ist unabhängig von der Geräte-UI und daher für das Testen von Geräten mit unterschiedlicher UI und Hardware skalierbar. Um diese Skalierbarkeit zu erreichen, verwendet Spectatio Standardgerätekonfigurationen, die auf dem Referenzgerät basieren. Zur Unterstützung von nicht standardmäßigen Gerätekonfigurationen verwendet das Framework zur Laufzeit eine JSON-Konfigurationsdatei, um die gewünschten UI-Änderungen für das Gerät festzulegen. Eine JSON-Konfigurationsdatei unterstützt UI-Elemente wie TEXT, DESCRIPTION und RESOURCE_ID sowie path-Einstellungen und darf nur die Informationen zu den UI-Änderungen für die DUT enthalten. Die übrigen UI-Elemente verwenden die im Framework bereitgestellten Standardkonfigurationswerte.

Standardgerätekonfigurationen

Die folgende Beispiel-JSON-Konfigurationsdatei zeigt die verfügbaren Gerätekonfigurationen und ihre Standardwerte.

Klicken Sie hier, um eine JSON-Beispielkonfigurationsdatei anzuzeigen

    {
        "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"
                        }
                }
        }
}
  

Alternative Gerätekonfigurationen

Das folgende Codebeispiel zeigt ein Beispiel für die JSON-Konfigurationsdatei, in der die Standardeinstellungen durch die Einstellungen des DUT überschrieben werden. In diesem Beispiel gilt Folgendes:

  • Die Interneteinstellungen heißen auf Referenzgeräten Netzwerk und Internet und auf dem DUT Konnektivität.

  • Die Datums- und Uhrzeiteinstellungen finden Sie für Referenzgeräte unter Einstellungen > Datum und Uhrzeit und für das DUT unter Einstellungen > System > Datum und Uhrzeit.

// 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"
    },
    ....
}

Sobald die JSON-Konfigurationsdatei fertig ist, wird sie zur Laufzeit bereitgestellt, wie im folgenden Codeblock gezeigt:

# Push The JSON configuration file to the device
adb -s DEVICE-SERIAL push PATH-OF-JSON-FILE /data/local/tmp/runtimeSpectatioConfig.json

In diesem Befehl gilt:

  • DEVICE-SERIAL: Seriennummer des DUT. Dieser Parameter ist nicht erforderlich, wenn nur ein Gerät mit dem Host verbunden ist.

  • PATH-TO-JSON-FILE: Pfad zur JSON-Datei auf dem Hostcomputer.

Konfigurationsformat

Die Konfiguration enthält fünf Objekte der obersten Ebene mit den folgenden Schlüsseln und Werten:

Objekt Beschreibung
PACKAGES Ein Objekt, das das Hauptpaket für verschiedene Apps beschreibt und anhand dessen ermittelt wird, wann diese App im Vordergrund ausgeführt wird.
ACTIONS Ein Objekt, das Aktionstypen und Parameter für verschiedene Aktionen angibt. Beispielsweise, ob zum Scrollen Schaltflächen oder eine Geste verwendet werden sollen.
COMMANDS Ein Objekt, das Befehle für verschiedene Aktionen angibt.
UI_ELEMENTS Ein Objekt, mit dem UI Automator-„BySelectors“ (UI-Elemente auswählen) erstellt werden (siehe unten).
WORKFLOWS Abfolgen von Aktionen, die allgemeine Aufgaben ausführen (siehe unten).

UI-Elemente

Jedes UI-Element hat ein TYPE, das angibt, wonach UI Automator suchen soll, um das Element zu identifizieren (z. B. Ressourcen-ID, Text und Beschreibung) und die mit diesem Typ verknüpften Konfigurationswerte. Im Allgemeinen wird bei der Identifizierung eines Elements auf dem Bildschirm mit dieser Konfiguration genau ein Element zurückgegeben. Wenn mehrere Elemente mit der Konfiguration übereinstimmen, wird im Test ein beliebiges Element verwendet. Daher sollte die Konfiguration (im Allgemeinen) so spezifisch formuliert sein, dass sie sich auf ein Element im relevanten Kontext eingrenzt.

TEXT

Dies ist der einfachste UI-Elementtyp. Das UI-Element wird anhand seines Texts identifiziert und erfordert eine genaue Übereinstimmung.

    "CALL_HISTORY_MENU": {
      "TYPE": "TEXT",
      "VALUE": "Recents"
    }

TEXT_ENTHÄLT

Entspricht TEXT, mit der Ausnahme, dass das angegebene VALUE nur irgendwo im Text des abzugleichenden Elements vorkommen muss.

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

BESCHREIBUNG

Das Element wird anhand des Attributs „content_description“ identifiziert. Es ist eine genaue Übereinstimmung erforderlich.

    "APP_GRID_SCROLL_BACKWARD_BUTTON": {
      "TYPE": "DESCRIPTION",
      "VALUE": "Scroll up"
    }

RESOURCE_ID

Identifizieren Sie das Element anhand seiner Ressourcen-ID und prüfen Sie optional auch die Paketkomponente dieser ID. Der Schlüssel PACKAGE ist optional. Wenn Sie ihn nicht angeben, stimmt jedes Paket überein und nur der Teil der ID nach :id/ wird berücksichtigt.

    "APP_LIST_SCROLL_ELEMENT": {
      "TYPE": "RESOURCE_ID",
      "VALUE": "apps_grid",
      "PACKAGE": "com.android.car.carlauncher"
    }

ANKLICKBAR, SCROLLBAR

Identifizieren Sie das Element danach, ob es anklickbar oder scrollbar ist. Dies sind sehr allgemeine Elementtypen und sollten im Allgemeinen nur in einem MULTIPLE verwendet werden, um einen anderen Elementtyp einzugrenzen. Der Schlüssel FLAG ist optional und standardmäßig true.

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

CLASS

Identifizieren Sie das Element anhand seiner Klasse.

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

HAS_ANCESTOR

Ermitteln Sie das Element, indem Sie in der Widget-Hierarchie nach seinen Vorfahren suchen. Der Schlüssel ANCESTOR enthält ein Objekt, das den übergeordneten Knoten identifiziert. Mit dem Schlüssel DEPTH wird angegeben, wie weit oben in der Hierarchie gesucht werden soll. DEPTH ist optional und hat den Standardwert 1.

      "SAMPLE_ELEMENT": {
      "TYPE": "HAS_ANCESTOR",
      "DEPTH": 2,
      "ANCESTOR": {
        "TYPE": "CLASS",
        "VALUE": "android.view.ViewGroup"
      }
    }

HAS_DESCENDANT

Suchen Sie in der Hierarchie nach den untergeordneten Elementen, um das Element zu identifizieren. Der Schlüssel DESCENDANT enthält ein Objekt, das das zu suchende untergeordnete Element angibt. Mit dem Schlüssel DEPTH wird angegeben, wie weit oben in der Hierarchie gesucht werden soll. DEPTH ist optional und hat den Standardwert 1.

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

MEHRERE

Das Element wird anhand mehrerer gleichzeitiger Bedingungen identifiziert, die alle erfüllt sein müssen.

      "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 diesem Beispiel wird in der Konfiguration ein RelativeLayout mit einem untergeordneten Element in der Tiefe 2 mit dem Text Permission manager angegeben.

Workflows

Ein Workflow stellt eine Abfolge von Aktionen dar, die zur Ausführung einer bestimmten Aufgabe verwendet werden. Diese kann sich von Gerät zu Gerät unterscheiden und ist in der Konfiguration flexibler darstellbar als im 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"
          }
        }
      }
    ]
  }

Jeder Workflow ist ein Schlüssel/Wert-Paar, wobei der Schlüssel der Name des Workflows und der Wert ein Array von auszuführenden Aktionen ist. Jede Aktion hat eine NAME, eine TYPE, (in der Regel) eine CONFIG und (manchmal) eine SWIPE_CONFIG oder SCROLL_CONFIG. Bei den meisten TYPEs ist CONFIG ein Objekt mit einem UI_ELEMENT-Schlüssel, dessen Wert dieselbe Form wie ein UI-Elementeingabe hat (siehe oben). Diese TYPEs sind:

DRÜCKEN
LANGE_DRÜCKEN
KLICKEN
LANGE_KLICKEN
KLICKEN_WENN_VORHANDEN
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

Für die anderen TYPEs gelten folgende Konfigurationsdetails:

Objekt Beschreibung
COMMAND Ein Objekt mit einem TEXT-Wert, der den auszuführenden Befehl enthält.
HAS_PACKAGE_IN_FOREGROUND Ein Objekt mit einem TEXT-Wert, das das Paket enthält.
SWIPE Lassen Sie bei einer SWIPE-Aktion die CONFIG key aus. Hier wird nur SWIPE_CONFIG verwendet.
WAIT_MS Ein Objekt mit einem TEXT-Wert, der die Anzahl der Millisekunden enthält, die gewartet werden soll.

Für Scroll- und Wischaktionen ist eine zusätzliche Konfiguration erforderlich:

SCROLL_CONFIG

Objekt Beschreibung
SCROLL_ACTION Entweder USE_GESTURE oder USE_BUTTON
SCROLL_DIRECTION Entweder HORIZONTAL oder VERTICAL
SCROLL_ELEMENT Ein Objekt, das den zu scrollenden Container angibt, mit demselben Formular wie bei der Konfiguration eines UI-Elements (siehe oben).
SCROLL_FORWARD, SCROLL_BACKWARD Die Schaltflächen zum Scrollen nach vorne und hinten (erforderlich, wenn SCROLL_ACTION = USE_BUTTON).
SCROLL_MARGIN Wenn SCROLL_ACTION = USE_GESTURE ist, ist dies der Abstand vom Rand des Containers, ab dem das Ziehen zum Scrollen gestartet und beendet wird (optional, Standardwert = 10).
SCROLL_WAIT_TIME Wenn SCROLL_ACTION USE_GESTURE ist, ist dies die Zeit in Millisekunden, die zwischen den Scroll-Gesten gewartet wird, wenn nach einem Objekt gesucht wird, auf das geklickt werden soll. Optional,Standardwert 1.

SWIPE_CONFIG

Objekt Beschreibung
SWIPE_DIRECTION Entweder TOP_TO_BOTTOM, BOTTOM_TO_TOP, LEFT_TO_RIGHT oder RIGHT_TO_LEFT
SWIPE_FRACTION

Eine der folgenden Optionen:

  • FULL: Wischen Sie vom Rand zum Rand des Displays.

    ODER
  • DEFAULT: Von Bildschirmrand zu Bildschirmrand mit einem Puffer von fünf (5) Pixeln auf jeder Seite.

    ODER
  • THREE_QUARTER, HALF oder QUARTER: Die Wischgeste endet fünf (5) Pixel vom Bildschirmrand entfernt und beginnt an einem Punkt, der die angegebene Entfernung auf dem Display abdeckt.
NUMBER_OF_STEPS Die Anzahl der Schritte, die für das Wischen verwendet werden sollen. segmentSteps ansehen.

Erstellen und ausführen

Das Spectatio-Framework wird automatisch als Teil des Test-APK erstellt. Zum Erstellen des Test-APKs muss sich die AOSP-Codebasis auf der lokalen Workstation befinden. Nachdem das Test-APK erstellt wurde, muss der Nutzer das APK auf dem Gerät installieren und den Test ausführen.

Das folgende Codebeispiel zeigt das Erstellen, Installieren und Ausführen eines Test-APKs.

# 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 diesen Befehlen gilt:

  • TEST-APK-NAME: Der Name der zu testenden App. Legen Sie beispielsweise TEST-APK-NAME auf AndroidAutomotiveSettingsTests fest, um die WLAN-Einstellungen zu testen, die in der Datei Android.bp angegeben sind. Den Namen des APK finden Sie in der entsprechenden Android.bp-Datei für den Automobiltest.

  • DEVICE-SERIAL: Die Seriennummer des DUT. Dieser Parameter ist nicht erforderlich, wenn nur ein Gerät mit dem Host verbunden ist.

  • config-file-path: Optionaler Parameter, der nur erforderlich ist, um nicht standardmäßige Geräte-UI-Konfigurationen anzugeben, wie in der JSON-Konfigurationsdatei angegeben. Wenn keine angegeben werden, verwendet das Framework Standardwerte für die Ausführung der Tests.

  • PATH-FOR-BUILT-TEST-APK: Der Pfad, unter dem das Test-APK erstellt wird, wenn der Befehl make ausgeführt wird.

  • TEST-PACKAGE: Der Name des Testpakets.

  • TEST-CLASSNAME: Der Name der Testklasse. Für den Test WLAN-Einstellungen lautet das Testpaket beispielsweise android.platform.tests und der Name der Testklasse WifiSettingTest.

Snippet-Bibliothek für die Automobilbranche

Die Automotive Snippet Library ist eine Reihe von Android-Testbibliotheken für das Android Open Source Project (AOSP), die für die Interaktion mit Apps und Diensten aus der Automobilbranche entwickelt wurden. Es nutzt Spectatio mit einem praktischen Mechanismus zur Ausführung von Remote Procedure Calls (RPCs) von einem Host- (Test-)Computer auf ein Android-Gerät.

Erste Schritte

Lesen Sie sich diese Abschnitte durch, bevor Sie beginnen.

Voraussetzungen

  • Python 3.x auf dem Hostcomputer installiert
  • AOSP-Umgebung mit den erforderlichen Build-Tools einrichten
  • Ein Android Automotive-Gerät (Emulator oder physisches Gerät) mit ADB-Zugriff.

Compilation

Sie können die verschiedenen Snippets aus der Snippet-Bibliothek für die Automobilbranche mithilfe der bereitgestellten Datei android.bp kompilieren. Führen Sie die Befehle im vorherigen Abschnitt aus, um das APK zu kompilieren.

Bereitstellung

Nachdem du die Snippet-Bibliotheken erfolgreich kompiliert hast, kannst du die resultierenden APKs mit dem im vorherigen Abschnitt erwähnten adb install-Befehl auf dem Zielgerät bereitstellen.

Tests ausführen

Die Snippet-Bibliotheken bieten mehrere RPC-Methoden für die Interaktion mit dem Automobilsystem. Diese Methoden können über das Mobly-Framework vom Hostcomputer aufgerufen werden. Wenn Sie die Mobly-Testumgebung eingerichtet haben, können Sie mit dem Script snippet_shell.py eine interaktive Python-Shell öffnen, in der Sie RPC-Methoden manuell auf dem Gerät aufrufen können. Beispielaufruf:

python3 snippet_shell.py com.google.android.mobly.snippet.bundled -s <serial>

Ersetzen Sie <serial> durch die Seriennummer des Geräts. Sie können sie mit „adb devices“ abrufen, wenn mehrere Geräte verbunden sind.

Enthaltene Bibliotheken

Die Snippet-Bibliothek für die Automobilbranche enthält die folgenden Snippet-Bibliotheken und ‑Hilfsprogramme:

  • AutomotiveSnippet: stellt APIs für Fahrzeugvorgänge wie Wähltasten, Lautstärkeregelung, feste Fahrzeugschlüssel und Interaktion mit dem Mediacenter bereit.

  • PhoneSnippet: Bietet telefonbezogene APIs, einschließlich Anrufverwaltung, Kontaktsuche und SMS-Vorgänge.

Das Snippet für die Automobilbranche und das PhoneSnippet haben einige gemeinsame Logik. Insbesondere können Sie Bluetooth-bezogene RCP-Anrufe manipulieren, um ein Auto und ein Smartphone zu koppeln. bt_discovery_test