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 Automotive-Gerät und ist eine erweiterbare und skalierbare Lösung zum Überprüfen der Funktionen und Leistung von AAOS und seinen Apps.

High-Level-Design

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

Die folgende Abbildung zeigt das High-Level-Design des Spectatio-Frameworks.

Übersicht über das Spectatio-Framework

Abbildung 1 : High-Level-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. Automotive-Tests verwenden die APIs des Spectatio-Frameworks zum Testen. Dadurch sind diese Tests unabhängig vom zu testenden Gerät (Device Under Test, DUT) und können zum Testen verschiedener Geräte skaliert werden, sofern dies unterstützt wird.

Abbildung 1 zeigt, dass das Spectatio-Framework basierend auf Referenz-Apps wie Dialer, Medicenter und Einstellungen mit app-spezifischen Schnittstellen und Hilfsmethoden modularisiert ist. Dadurch lässt es sich problemlos 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 oder für alle Apps anwendbar sind. Die Dienstprogramm-Hilfsklassen bieten Dienstprogramme wie das Lesen oder Schreiben von Dateien vom Gerät.

Architektur

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

Abbildung 2 zeigt die High-Level-Architektur des Spectatio-Frameworks und alle Entitäten, die an der Implementierung von APIs zum Testen einer App beteiligt sind.

Übersicht über die Spectatio-Framework-Architektur

Abbildung 2 : High-Level-Architektur des Spectatio-Frameworks.

Die App-Hilfsschnittstelle bietet eine Vorlage für die Implementierung einer App-Hilfsmethode. Sie besteht aus verschiedenen Hilfsfunktionen, die zum Testen von Apps erforderlich sind. Jede App hat eine eigene Schnittstelle, z. B. IAutoSettingHelper und IAutoDialHelper. Weitere Informationen und eine Liste der Schnittstellenfunktionen finden Sie unter den App-Hilfsschnittstellenfunktionen in AOSP.

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

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

Das Modul zur Implementierung der App-Hilfsmethode ist das Herzstück des Spectatio-Frameworks. Es enthält die Implementierung für die in der App-Hilfsschnittstelle definierten Hilfsfunktionen, die zum Testen von Apps auf einem Automotive-Gerät erforderlich sind. Jede App hat eine eigene Implementierung, z. B. SettingHelperImpl und DialHelperImpl, die von den Automotive-Tests zum Testen der Apps verwendet werden. Weitere Informationen und eine Liste der Implementierungen finden Sie unter App-Hilfsimplementierungsfunktionen 'in AOSP.

Automotive-Tests verwenden die Implementierungsfunktionen der App-Hilfsmethode, um verschiedene Vorgänge im Zusammenhang mit der App zu testen. Verwenden Sie die Klasse HelperAccessor , um auf die Implementierungsfunktionen der App-Hilfsmethode zuzugreifen.

Der folgende Code zeigt die Einrichtung, Bereinigung und Ausführung eines Automotive-Beispieltests.

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

Anpassung

Das Spectatio-Framework ist unabhängig von der Geräte-UI und kann daher zum Testen von Geräten mit unterschiedlichen UIs und Hardware skaliert werden. 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 Informationen zu den UI-Änderungen für das DUT enthalten. Für die übrigen UI-Elemente werden die im Framework bereitgestellten Standardkonfigurationswerte verwendet.

Standardgerätekonfigurationen

Die folgende JSON-Beispielkonfigurationsdatei 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 auf dem DUT überschrieben werden. In diesem Beispiel gilt Folgendes:

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

  • Die Einstellungen für Datum und Uhrzeit sind auf Referenzgeräten unter Einstellungen > Datum und Uhrzeit und auf dem DUT unter Einstellungen > System > Datum und Uhrzeit verfügbar.

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

Wenn 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

Dabei gilt:

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

  • PATH-TO-JSON-FILE: Pfad der 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, mit dem ermittelt wird, wann sich die App im Vordergrund befindet.
ACTIONS Ein Objekt, das Aktionstypen und Parameter für verschiedene Aktionen angibt. Beispielsweise, ob zum Scrollen Schaltflächen oder eine Touchgeste verwendet werden sollen.
COMMANDS Ein Objekt, das Befehle angibt, mit denen verschiedene Aktionen ausgeführt werden.
UI_ELEMENTS Ein Objekt, das zum Erstellen von UI Automator-`BySelectors` verwendet wird, mit denen UI Elemente ausgewählt werden (siehe unten).
WORKFLOWS Sequenzen von Aktionen, mit denen übergeordnete Aufgaben ausgeführt werden (siehe unten).

UI-Elemente

Jedes UI-Element hat einen TYPE, der angibt, wonach UI Automator suchen soll, um das Element zu identifizieren (z. B. Ressourcen-ID, Text und Beschreibung), sowie Konfigurationswerte, die mit diesem Typ verknüpft sind. Wenn eine Hilfsmethode mit dieser Konfiguration ein Element auf dem Bildschirm identifiziert, wird genau ein Element zurückgegeben. Wenn mehrere Elemente mit der Konfiguration übereinstimmen, wird ein beliebiges Element im Test verwendet. Daher sollte die Konfiguration (im Allgemeinen) so spezifisch sein, dass sie im relevanten Kontext auf ein Element beschränkt wird.

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_CONTAINS

Wie TEXT, mit dem Unterschied, dass der angegebene VALUE nur irgendwo im Text des Elements vorkommen muss, um eine Übereinstimmung zu erzielen.

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

BESCHREIBUNG

Identifizieren Sie das Element anhand des Attributs für die Inhaltsbeschreibung. Eine genaue Übereinstimmung ist 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 er weggelassen wird, 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"
    }

CLICKABLE, SCROLLABLE

Identifizieren Sie das Element danach, ob es anklickbar oder scrollbar ist. Dies sind sehr allgemeine Elementtypen, die in der Regel nur in einem MULTIPLE verwendet werden sollten, um einen anderen Elementtyp einzugrenzen. Der Schlüssel FLAG ist optional und hat standardmäßig den Wert 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

Identifizieren Sie das Element, indem Sie die Widget-Hierarchie nach seinen Vorgängern durchsuchen. Der Schlüssel ANCESTOR enthält ein Objekt, das den Vorgänger identifiziert. Der Schlüssel DEPTH gibt an, wie weit 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

Identifizieren Sie das Element, indem Sie die Hierarchie nach seinen untergeordneten Elementen durchsuchen. Der Schlüssel DESCENDANT enthält ein Objekt, das das untergeordnete Element angibt, nach dem gesucht werden soll. Der Schlüssel DEPTH gibt an, wie weit 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"
      }
    }

MULTIPLE

Identifizieren Sie das Element anhand mehrerer gleichzeitiger Bedingungen, 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 identifiziert die Konfiguration ein RelativeLayout mit einem untergeordneten Element in Tiefe 2, das den Text Permission manager enthält.

Workflows

Ein Workflow stellt eine Sequenz von Aktionen dar, die zum Ausführen einer bestimmten Aufgabe verwendet werden. Diese kann sich von Gerätetyp zu Gerätetyp erheblich unterscheiden und lässt sich in der Konfiguration flexibler darstellen 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 einen NAME, einen TYPE, (in der Regel) eine CONFIG und (manchmal) eine SWIPE_CONFIG oder SCROLL_CONFIG. Für die meisten TYPEs ist die CONFIG ein Objekt mit einem UI_ELEMENT-Schlüssel, dessen Wert dieselbe Form wie ein UI-Elementeintrag hat (siehe oben). Diese TYPEs sind:

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

Für die anderen TYPEs sind die 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, der das Paket enthält.
SWIPE Lassen Sie den CONFIG key für eine SWIPE Aktion weg. 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. Es hat dieselbe Form wie eine UI Elementkonfiguration (siehe oben).
SCROLL_FORWARD, SCROLL_BACKWARD Die Schaltflächen zum Vorwärts- und Rückwärtsscrollen (erforderlich, wenn SCROLL_ACTION auf USE_BUTTON gesetzt ist).
SCROLL_MARGIN Wenn SCROLL_ACTION auf USE_GESTURE gesetzt ist, ist dies der Abstand vom Rand des Containers, an dem das Ziehen gestartet und beendet wird, um zu scrollen (optional, Standardwert = 10).
SCROLL_WAIT_TIME Wenn SCROLL_ACTION auf USE_GESTURE gesetzt ist, ist dies die Zeit in Millisekunden, die zwischen den Scrollgesten gewartet wird, wenn nach einem anzuklickenden Objekt gesucht wird. (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

Einer der folgenden Werte:

  • FULL: Wischgeste vom Bildschirmrand zum Bildschirmrand

    ODER,
  • DEFAULT: Vom Bildschirmrand zum 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, sodass die angegebene Entfernung des Bildschirms abgedeckt wird.
NUMBER_OF_STEPS Die Anzahl der Schritte, die zum Ausführen der Wischgeste verwendet werden sollen. Siehe segmentSteps.

Erstellen und ausführen

Das Spectatio-Framework wird automatisch als Teil des Test-APKs 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

Dabei gilt:

  • TEST-APK-NAME: Der Name der zu testenden App. Setzen Sie beispielsweise TEST-APK-NAME auf AndroidAutomotiveSettingsTests, um die WLAN-Einstellungen wie in der Datei Android.bp angegeben zu testen. Der Name des APKs ist in der jeweiligen Android.bp Datei für den Automotive-Test zu finden.

  • DEVICE-SERIAL: Die Serien-ID 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 er nicht angegeben wird, verwendet das Framework Standardwerte für die Ausführung der Tests.

  • PATH-FOR-BUILT-TEST-APK: Der Pfad, in 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 der WLAN-Einstellungen ist das Testpaket beispielsweise android.platform.tests und der Name der Testklasse WifiSettingTest.

Automotive-Snippet-Bibliothek

Die Automotive-Snippet-Bibliothek ist eine Reihe von Android-Testbibliotheken für das Open-Source-Projekt für Android (AOSP), die für die Interaktion mit Automotive-Apps und ‑Diensten entwickelt wurden. Sie nutzt Spectatio mit einem praktischen Mechanismus zum Ausführen von Remoteprozeduraufrufen (Remote Procedure Calls, RPCs) von einem Hostcomputer (Testcomputer) zu einem Android-Gerät.

Jetzt starten

Lesen Sie zuerst die folgenden Abschnitte.

Vorbereitung

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

Compilation

Um die verschiedenen Snippets der Automotive-Snippet-Bibliothek zu kompilieren, können Sie die bereitgestellte Datei android.bp verwenden. Führen Sie die Befehle im vorherigen Abschnitt aus, um das APK zu kompilieren.

Bereitstellung

Nachdem Sie die Snippet-Bibliotheken erfolgreich kompiliert haben, stellen Sie die resultierenden APKs mit dem Befehl adb install aus dem vorherigen Abschnitt auf dem Zielgerät bereit.

Tests ausführen

Die Snippet-Bibliotheken stellen mehrere RPC-Methoden zur Interaktion mit dem Automotive-System bereit. Diese Methoden können über das Mobly-Framework vom Hostcomputer aus aufgerufen werden. Wenn Sie die Mobly-Testumgebung eingerichtet haben, können Sie mit dem snippet_shell.py Skript 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 Automotive-Snippet-Bibliothek enthält die folgenden Snippet-Bibliotheken und Hilfsmethoden:

  • AutomotiveSnippet: Bietet APIs für Fahrzeugvorgänge wie Wählen, Lautstärkeregelung, Fahrzeugtasten und Interaktion mit dem Media Center.

  • PhoneSnippet: Bietet APIs für die Telefonie, einschließlich Anrufverwaltung, Kontaktsuche und SMS-Vorgänge.

Das Automotive-Snippet und das PhoneSnippet verwenden dieselbe Logik. Insbesondere können Sie Bluetooth-bezogene RCP-Aufrufe verwenden, um ein Automotive-Gerät und ein Smartphone zu koppeln. Das bt_discovery_test zeigt, wie das geht.