Spectatio: Automotive-Test-Framework

Spectatio ist ein Open-Source-Testframework, das zum Testen von Android Automotive OS (AAOS) auf realen und virtuellen Geräten entwickelt wurde. Spectatio stellt APIs zum Testen von Apps auf einem Automobilgerät bereit und ist eine erweiterbare und skalierbare Lösung zur Überprüfung der Leistungsfähigkeit und Leistung von AAOS und seinen Apps.

Design auf hohem Niveau

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

Die folgende Abbildung erläutert das allgemeine Design des Spectatio-Frameworks.

High-Level-Design des Spectatio-Frameworks

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 Benutzer- und System-Apps unter AAOS interagieren. Automotive-Tests nutzen die vom Spectatio-Framework bereitgestellten APIs zum Testen, wodurch diese Tests unabhängig vom zu testenden Gerät (DUT) und skalierbar sind, um verschiedene Geräte zu testen, sofern unterstützt.

Abbildung 1 zeigt, dass das Spectatio-Framework auf Basis von Referenz-Apps wie Dialer, Medicenter und Settings unter Verwendung appspezifischer Schnittstellen und Hilfsprogramme modularisiert ist, wodurch es leicht für neue Apps erweiterbar ist. Das Spectatio-Framework verwendet die allgemeinen Standard- und Utility-Hilfsklassen wieder. Die Standard-Hilfsklasse ist die übergeordnete Klasse für alle App-Hilfsfunktionen und stellt Standardfunktionen bereit, die gerätespezifisch oder app-übergreifend anwendbar sind. Die Utility-Hilfsklassen stellen Dienstprogramme wie das Lesen oder Schreiben von Dateien vom Gerät bereit.

Die Architektur

Um eine Reihe von APIs zum Erstellen von UI-Tests bereitzustellen, implementiert das Spectatio-Framework anwendungsspezifische Schnittstellen und Helfer, erweitert gleichzeitig die vorhandene Standard-Hilfsklasse und importiert die Hilfshilfsklassen.

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

High-Level-Architektur des Spectatio-Frameworks

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

Die App-Helper-Schnittstelle bietet einen Entwurf für die Implementierung eines App-Helfers. Es besteht aus verschiedenen Hilfsfunktionen, die zum Testen von Apps benötigt werden. Jede App verfügt über eine eigene Schnittstelle, z. B. IAutoSettingHelper und IAutoDialHelper . Weitere Informationen und eine Liste der Schnittstellenfunktionen finden Sie in den App-Helper-Schnittstellenfunktionen auf AOSP.

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

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

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

Automotive-Tests verwenden die App-Helper-Implementierungsfunktionen, um verschiedene Vorgänge im Zusammenhang mit der App zu testen. Verwenden Sie die Klasse HelperAccessor , um Zugriff auf die Implementierungsfunktionen des App-Helfers zu erhalten.

Der folgende Code zeigt die Einrichtung, Bereinigung und Ausführung eines Beispiel-Automobiltests.

@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 Benutzeroberfläche des Geräts und kann daher zum Testen von Geräten mit unterschiedlichen Benutzeroberflächen und Hardware skaliert werden. Um diese Skalierbarkeit zu erreichen, verwendet Spectatio Standardgerätekonfigurationen basierend auf dem Referenzgerät. Um nicht standardmäßige Gerätekonfigurationen zu unterstützen, 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 und darf nur Informationen zu den UI-Änderungen für das 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 Beispiel-JSON-Konfigurationsdatei 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 der JSON-Konfigurationsdatei, in der Standardeinstellungen durch die Einstellungen auf dem DUT überschrieben werden. In diesem Beispiel:

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

  • Die Datums- und Uhrzeiteinstellungen sind unter Einstellungen > Datum und Uhrzeit für Referenzgeräte und unter Einstellungen > System > Datum und Uhrzeit für das DUT 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

In diesem Befehl:

  • 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 der JSON-Datei auf dem Host-Computer.

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 steht.
ACTIONS Ein Objekt, das Aktionstypen und Parameter für verschiedene Aktionen angibt. Zum Beispiel, ob zum Scrollen Tasten oder eine Geste verwendet werden sollen.
COMMANDS Ein Objekt, das Befehle angibt, die verschiedene Aktionen ausführen.
UI_ELEMENTS Ein Objekt, das zum Erstellen von UI Automator „BySelectors“ verwendet wird, die UI-Elemente auswählen (unten ausführlich beschrieben).
WORKFLOWS Abfolgen von Aktionen, die hochrangige Aufgaben erfüllen (unten ausführlich beschrieben).

UI-Elemente

Jedes UI-Element verfügt über einen TYPE , der angibt, wonach UI Automator sucht, um das Element zu identifizieren (z. B. Ressourcen-ID, Text und Beschreibung) und Konfigurationswerte, die diesem Typ zugeordnet sind. Wenn ein Helfer mithilfe dieser Konfiguration ein Element auf dem Bildschirm identifiziert, erhält er im Allgemeinen genau ein Element. Wenn mehrere Elemente mit der Konfiguration übereinstimmen, wird im Test ein beliebiges verwendet. Daher sollte die Konfiguration (im Allgemeinen) so spezifisch geschrieben werden, dass sie sich auf ein Element im relevanten Kontext beschränkt.

TEXT

Dies ist der einfachste UI-Elementtyp. Das UI-Element wird durch seinen Text identifiziert und erfordert eine genaue Übereinstimmung.

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

TEXT_CONTAINS

Identisch mit TEXT , außer dass der angegebene VALUE nur irgendwo im Text des zu vergleichenden Elements erscheinen muss.

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

BESCHREIBUNG

Identifizieren Sie das Element anhand seines Inhaltsbeschreibungsattributs, das eine genaue Übereinstimmung erfordert.

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

RESOURCE_ID

Identifizieren Sie das Element anhand seiner Ressourcen-ID und überprüfen Sie optional auch die Paketkomponente dieser ID. Der PACKAGE Schlüssel ist optional; Wenn es weggelassen wird, stimmt jedes Paket überein und nur der Teil der ID, der auf :id/ folgt, wird berücksichtigt.

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

ANKLICKBAR, SCROLLBAR

Identifizieren Sie das Element anhand dessen, ob es anklickbar oder scrollbar ist (oder nicht). Dies sind sehr weit gefasste Elementtypen und sollten im Allgemeinen nur in einem MULTIPLE verwendet werden, um einen anderen Elementtyp einzugrenzen. Der FLAG Schlüssel ist optional und hat standardmäßig den Wert true .

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

KLASSE

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 bei seinen Vorgängern nachschlagen. Der ANCESTOR Schlüssel enthält ein Objekt, das den Vorfahren identifiziert. Der Schlüssel DEPTH gibt an, 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

Identifizieren Sie das Element, indem Sie in der Hierarchie nach unten auf seine untergeordneten Elemente schauen. Der DESCENDANT Schlüssel enthält ein Objekt, das das zu suchende Kind angibt. Der Schlüssel DEPTH gibt an, 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

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 , das einen Nachkommen in der Tiefe 2 hat, der den Text Permission manager hat.

Arbeitsabläufe

Ein Workflow stellt eine Abfolge von Aktionen dar, die zum Ausführen einer bestimmten Aufgabe verwendet werden. Diese können sich von Gerätetyp zu Gerätetyp ausreichend unterscheiden und lassen 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 , (normalerweise) einen CONFIG und (manchmal) einen SWIPE_CONFIG oder SCROLL_CONFIG . Bei den meisten TYPEs ist CONFIG ein Objekt mit einem UI_ELEMENT -Schlüssel, dessen Wert die gleiche Form wie ein UI-Elementeintrag annimmt (siehe oben). Diese TYPEN sind:

DRÜCKEN SIE
LANGE DRÜCKEN
KLICKEN
LANGER_KLICK
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 TYPEn lauten 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, das das Paket enthält.
SWIPE Lassen Sie die CONFIG key für eine SWIPE Aktion weg. Dies verwendet nur SWIPE_CONFIG
WAIT_MS Ein Objekt mit einem TEXT Wert, der die Anzahl der zu wartenden Millisekunden enthält.

Scroll- und Wischaktionen erfordern eine zusätzliche Konfiguration wie folgt:

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 und das gleiche Formular wie eine UI-Element-Konfiguration verwendet (siehe oben).
SCROLL_FORWARD , SCROLL_BACKWARD Die Vorwärts- und Rückwärts-Bildlaufschaltflächen (erforderlich, wenn SCROLL_ACTION USE_BUTTON hat).
SCROLL_MARGIN Wenn SCROLL_ACTION USE_GESTURE ist, der Abstand vom Rand des Containers zum Starten und Stoppen des Ziehens, der zum Durchführen des Bildlaufs verwendet wird ( Optional, Standard = 10).
SCROLL_WAIT_TIME Wenn SCROLL_ACTION USE_GESTURE ist, die Zeit in Millisekunden, die zwischen Bildlaufgesten gewartet werden muss, wenn nach einem Objekt zum Klicken gesucht wird. ( Optional, Standard = 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:

  • FULL : Wischen Sie mit der Geste von Bildschirmrand zu Bildschirmrand

    ODER,
  • DEFAULT : Bildschirmkante zu Bildschirmkante, 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 Rand des Bildschirms entfernt und beginnt an dem Punkt, an dem sie die angegebene Entfernung des Bildschirms abdeckt.
NUMBER_OF_STEPS Die Anzahl der Schritte, die zum Durchführen des Wischens verwendet werden sollen. Siehe segmentSteps .

Erstellen und ausführen

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

Das folgende Codebeispiel zeigt die Erstellung, Installation und Ausführung eines Test-APK.

# 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:

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

  • 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 bereitzustellen, wie in der JSON-Konfigurationsdatei angegeben. Sofern nicht angegeben, 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 WLAN-Einstellungen -Test lautet das Testpaket beispielsweise android.platform.tests und der Name der Testklasse lautet WifiSettingTest .

Automotive-Snippet-Bibliothek

Die Automotive Snippet Library ist eine Reihe von Android-Testbibliotheken für das Android Open Source Project (AOSP), die für die Interaktion mit Automobil-Apps und -Diensten konzipiert sind. Es nutzt Spectatio mit einem praktischen Mechanismus zum Ausführen von Remote Procedure Calls (RPCs) von einem Host-(Test-)Rechner auf einem Android-Gerät.

Loslegen

Bevor Sie beginnen, lesen Sie diese Abschnitte durch.

Voraussetzungen

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

Zusammenstellung

Um die verschiedenen von der Automotive Snippet Library bereitgestellten Snippets zu kompilieren, können Sie die bereitgestellte Datei android.bp verwenden. Befolgen Sie die Befehle im vorherigen Abschnitt, um das APK zu kompilieren.

Einsatz

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

Führen Sie Tests durch

Die Snippet-Bibliotheken stellen mehrere RPC-Methoden für die Interaktion mit dem Automobilsystem bereit. Diese Methoden können über das Mobly-Framework vom Host-Computer aus aufgerufen werden. Vorausgesetzt, Sie haben die Mobly-Testumgebung eingerichtet, können Sie mit dem Skript 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, die Sie mit adb devices erhalten können, wenn mehrere Geräte angeschlossen sind.

Enthaltene Bibliotheken

Die Automotive Snippet Library umfasst die folgenden Snippet-Bibliotheken und Helfer:

  • AutomotiveSnippet: Stellt APIs für den Fahrzeugbetrieb bereit, z. B. Wählen, Lautstärkeregelung, Fahrzeug-Hardkeys und Media-Center-Interaktion.

  • PhoneSnippet: Stellt telefoniebezogene APIs bereit, einschließlich Anrufbearbeitung, Durchsuchen von Kontakten und SMS-Vorgängen.

Das Automotive-Snippet und das PhoneSnippet haben eine gemeinsame Logik. Insbesondere können Sie in Bluetooth-bezogene RCP-Anrufe eindringen, um ein Fahrzeug und ein Telefongerät zu koppeln. Dieser bt_discovery_test zeigt wie.