Spectatio: Ramy testów motoryzacyjnych

Spectatio to platforma testowa typu open source opracowana do testowania systemu operacyjnego Android Automotive OS (AAOS) na urządzeniach rzeczywistych i wirtualnych. Spectatio udostępnia interfejsy API do testowania aplikacji na urządzeniu samochodowym oraz jest rozszerzalnym i skalowalnym rozwiązaniem służącym do sprawdzania możliwości i wydajności AAOS i jego aplikacji.

Projekt na wysokim poziomie

Framework Spectatio można dostosowywać i rozszerzać pod kątem różnych implementacji interfejsu użytkownika AAOS. Służy do testowania możliwości i wydajności AAOS na sprzęcie urządzenia, emulatorach i środowiskach zwirtualizowanych.

Poniższy rysunek wyjaśnia ogólny projekt frameworku Spectatio.

Wysoki poziom projektowania platformy Spectatio

Rysunek 1. Projekt wysokiego poziomu frameworku Spectatio.

Zbudowana na bazie UI Automator platforma Spectatio udostępnia zestaw interfejsów API do tworzenia testów interfejsu użytkownika, które wchodzą w interakcję z aplikacjami użytkownika i systemowymi w AAOS. Testy samochodowe wykorzystują do testowania interfejsy API dostarczane przez platformę Spectatio, co czyni te testy niezależnymi od testowanego urządzenia (DUT) i skalowalnymi w celu testowania różnych urządzeń, jeśli są obsługiwane.

Rysunek 1 pokazuje, że środowisko Spectatio jest zmodularyzowane w oparciu o aplikacje referencyjne, takie jak Dialer, Medicenter i Ustawienia, korzystające z interfejsów i pomocników specyficznych dla aplikacji, dzięki czemu można je łatwo rozszerzyć o nowe aplikacje. Framework Spectatio ponownie wykorzystuje wspólne klasy standardowe i pomocnicze. Standardowa klasa pomocnicza jest klasą nadrzędną dla wszystkich funkcji pomocniczych aplikacji i udostępnia standardowe funkcje, które są specyficzne dla urządzenia lub mają zastosowanie w różnych aplikacjach. Klasy pomocnicze narzędzi zapewniają narzędzia, takie jak odczytywanie i zapisywanie plików z urządzenia.

Architektura

Aby zapewnić zestaw interfejsów API do tworzenia testów interfejsu użytkownika, platforma Spectatio implementuje interfejsy i pomocniki specyficzne dla aplikacji, jednocześnie rozszerzając istniejącą standardową klasę pomocnika i importując klasy pomocników narzędzi.

Rysunek 2 ilustruje architekturę wysokiego poziomu frameworku Spectatio i wszystkie podmioty zaangażowane we wdrażanie interfejsów API do testowania aplikacji.

Architektura wysokiego poziomu platformy Spectatio

Rysunek 2. Architektura wysokiego poziomu platformy Spectatio.

Interfejs pomocnika aplikacji zapewnia plan implementacji pomocnika aplikacji. Składa się z różnych funkcji pomocniczych potrzebnych do testowania aplikacji. Każda aplikacja ma swój własny interfejs, taki jak IAutoSettingHelper i IAutoDialHelper . Aby uzyskać więcej informacji i listę funkcji interfejsu, zobacz funkcje interfejsu pomocniczego aplikacji w AOSP.

Standardowa klasa pomocnicza składa się ze standardowych atrybutów i funkcji wymaganych do konfiguracji urządzenia, ale nie jest specyficznych dla żadnej aplikacji, takich jak pressHome i scroll . Standardowa klasa pomocnicza jest zdefiniowana w AbstractAutoStandardAppHelper.java .

Klasy pomocnicze narzędzi są używane przez platformę. Na przykład AutoJsonUtility.java to klasa narzędziowa, która ładuje plik konfiguracyjny JSON danego urządzenia i aktualizuje konfiguracje struktury w czasie wykonywania.

Moduł implementacji pomocnika aplikacji stanowi rdzeń frameworka Spectatio. Zawiera implementację funkcji pomocniczych zdefiniowanych w interfejsie pomocniczym aplikacji, które są wymagane do testowania aplikacji na urządzeniu motoryzacyjnym. Każda aplikacja ma własną implementację, taką jak SettingHelperImpl i DialHelperImpl , używaną w testach motoryzacyjnych do testowania aplikacji. Aby uzyskać więcej informacji i listę implementacji, zobacz funkcje implementacji pomocnika aplikacji „w AOSP.

Testy samochodowe wykorzystują funkcje implementacji pomocnika aplikacji do testowania różnych operacji związanych z aplikacją. Użyj klasy HelperAccessor , aby uzyskać dostęp do funkcji implementacji pomocnika aplikacji.

Poniższy kod przedstawia konfigurację, czyszczenie i wykonanie przykładowego testu samochodowego.

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

Dostosowywanie

Struktura Spectatio jest niezależna od interfejsu użytkownika urządzenia, dzięki czemu jest skalowalna w celu testowania urządzeń z różnymi interfejsami użytkownika i sprzętem. Aby osiągnąć tę skalowalność, Spectatio wykorzystuje domyślne konfiguracje urządzeń oparte na urządzeniu referencyjnym. Aby obsługiwać konfiguracje urządzeń inne niż domyślne, platforma używa pliku konfiguracyjnego JSON w czasie wykonywania, aby ustawić żądane zmiany interfejsu użytkownika dla urządzenia. Plik konfiguracyjny JSON obsługuje elementy interfejsu użytkownika, takie jak TEXT , DESCRIPTION i RESOURCE_ID , wraz z ustawieniami path i musi zawierać tylko informacje o zmianach interfejsu użytkownika dla testowanego urządzenia. Pozostałe elementy interfejsu użytkownika korzystają z domyślnych wartości konfiguracyjnych dostarczonych w ramach.

Domyślne konfiguracje urządzeń

Poniższy przykładowy plik konfiguracyjny JSON przedstawia dostępne konfiguracje urządzeń i ich wartości domyślne.

Kliknij tutaj, aby wyświetlić przykładowy plik konfiguracyjny JSON

    {
        "SETTINGS": {
                "APPLICATION_CONFIG": {
                        "SETTINGS_TITLE_TEXT": "Settings",
                        "SETTINGS_PACKAGE": "com.android.car.settings",
                        "SETTINGS_RRO_PACKAGE": "com.android.car.settings.googlecarui.rro",
                        "OPEN_SETTINGS_COMMAND": "am start -a android.settings.SETTINGS",
                        "OPEN_QUICK_SETTINGS_COMMAND": "am start -n com.android.car.settings/com.android.car.settings.common.CarSettingActivity"
                },
                "QUICK_SETTINGS": {
                        "OPEN_MORE_SETTINGS": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "toolbar_menu_item_1",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "NIGHT_MODE": {
                                "TYPE": "TEXT",
                                "VALUE": "Night mode"
                        }
                },
                "DISPLAY": {
                        "PATH": "Settings > Display",
                        "OPTIONS": [
                                "Brightness level"
                        ],
                        "BRIGHTNESS_LEVEL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "seekbar",
                                "PACKAGE": "com.android.car.settings"
                        }
                },
                "SOUND": {
                        "PATH": "Settings > Sound",
                        "OPTIONS": [
                                "Media volume",
                                "Alarm volume"
                        ]
                },
                "NETWORK_AND_INTERNET": {
                        "PATH": "Settings > Network & internet",
                        "OPTIONS": [
                        ],
                        "TOGGLE_WIFI": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "master_switch",
                                "PACKAGE": "com.android.car.settings"
                        }
                },
                "BLUETOOTH": {
                        "PATH": "Settings > Bluetooth",
                        "OPTIONS": [
                        ],
                        "TOGGLE_BLUETOOTH": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_menu_item_switch",
                                "PACKAGE": "com.android.car.settings"
                        }
                },
                "APPS_AND_NOTIFICATIONS": {
                        "PATH": "Settings > Apps & notifications",
                        "OPTIONS": [
                        ],
                        "SHOW_ALL_APPS": {
                                "TYPE": "TEXT",
                                "VALUE": "Show all apps"
                        },
                        "ENABLE_DISABLE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_menu_item_text",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "DISABLE_BUTTON_TEXT": {
                                "TYPE": "TEXT",
                                "VALUE": "Disable"
                        },
                        "ENABLE_BUTTON_TEXT": {
                                "TYPE": "TEXT",
                                "VALUE": "Enable"
                        },
                        "DISABLE_APP_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "DISABLE APP"
                        },
                        "FORCE_STOP_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Force stop"
                        },
                        "OK_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "OK"
                        },
                        "PERMISSIONS_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Permissions"
                        },
                        "ALLOW_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Allow"
                        },
                        "DENY_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Deny"
                        },
                        "DENY_ANYWAY_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Deny anyway"
                        }
                },
                "DATE_AND_TIME": {
                        "PATH": "Settings > Date & time",
                        "OPTIONS": [
                                "Automatic date & time",
                "Automatic time zone"
                        ],
                        "AUTOMATIC_DATE_AND_TIME": {
                                "TYPE": "TEXT",
                                "VALUE": "Automatic date & time"
                        },
                        "AUTOMATIC_TIME_ZONE": {
                                "TYPE": "TEXT",
                                "VALUE": "Automatic time zone"
                        },
                        "SET_DATE": {
                                "TYPE": "TEXT",
                                "VALUE": "Set date"
                        },
                        "SET_TIME": {
                                "TYPE": "TEXT",
                                "VALUE": "Set time"
                        },
                        "SELECT_TIME_ZONE": {
                                "TYPE": "TEXT",
                                "VALUE": "Select time zone"
                        },
                        "USE_24_HOUR_FORMAT": {
                                "TYPE": "TEXT",
                                "VALUE": "Use 24-hour format"
                        },
                        "OK_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "toolbar_menu_item_0",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "NUMBER_PICKER_WIDGET": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.NumberPicker"
                        },
                        "EDIT_TEXT_WIDGET": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        }
                },
                "USERS": {
                        "PATH": "Settings > Users",
                        "OPTIONS": [
                                "Guest"
                        ]
                },
                "ACCOUNTS": {
                        "PATH": "Settings > Accounts",
                        "OPTIONS": [
                                "Automatically sync data"
                        ],
                        "ADD_ACCOUNT": {
                                "TYPE": "TEXT",
                                "VALUE": "ADD ACCOUNT"
                        },
                        "ADD_GOOGLE_ACCOUNT": {
                                "TYPE": "TEXT",
                                "VALUE": "Google"
                        },
                        "SIGN_IN_ON_CAR_SCREEN": {
                                "TYPE": "TEXT",
                                "VALUE": "Sign in on car screen"
                        },
                        "GOOGLE_SIGN_IN_SCREEN": {
                                "TYPE": "TEXT",
                                "VALUE": "Sign in to your Google Account"
                        },
                        "ENTER_EMAIL": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        },
                        "ENTER_PASSWORD": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        },
                        "NEXT_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Next"
                        },
                        "DONE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Done"
                        },
                        "REMOVE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Remove"
                        },
                        "REMOVE_ACCOUNT_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Remove Account"
                        }
                },
                "SYSTEM": {
                        "PATH": "Settings > System",
                        "OPTIONS": [
                                "About", "Legal information"
                        ],
                        "ABOUT_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "About"
                        },
                        "RESET_OPTIONS_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Reset options"
                        },
                        "LANGUAGES_AND_INPUT_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Languages & input"
                        },
                        "DEVICE_MODEL": {
                                "TYPE": "TEXT",
                                "VALUE": "Model"
                        },
                        "ANDROID_VERSION": {
                                "TYPE": "TEXT",
                                "VALUE": "Android version"
                        },
                        "ANDROID_SECURITY_PATCH_LEVEL": {
                                "TYPE": "TEXT",
                                "VALUE": "Android security patch level"
                        },
                        "KERNEL_VERSION": {
                                "TYPE": "TEXT",
                                "VALUE": "Kernel version"
                        },
                        "BUILD_NUMBER": {
                                "TYPE": "TEXT",
                                "VALUE": "Build number"
                        },
                        "RECYCLER_VIEW_WIDGET": {
                                "TYPE": "CLASS",
                                "VALUE": "androidx.recyclerview.widget.RecyclerView"
                        },
                        "RESET_NETWORK": {
                                "TYPE": "TEXT",
                                "VALUE": "Reset network"
                        },
                        "RESET_SETTINGS": {
                                "TYPE": "TEXT",
                                "VALUE": "RESET SETTINGS"
                        },
                        "RESET_APP_PREFERENCES": {
                                "TYPE": "TEXT",
                                "VALUE": "Reset app preferences"
                        },
                        "RESET_APPS": {
                                "TYPE": "TEXT",
                                "VALUE": "RESET APPS"
                        },
                        "LANGUAGES_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Languages"
                        },
                        "LANGUAGES_MENU_IN_SELECTED_LANGUAGE": {
                                "TYPE": "TEXT",
                                "VALUE": "Idiomas"
                        }
                },
                "SECURITY": {
                        "PATH": "Settings > Security",
                        "OPTIONS": [
                        ],
                        "TITLE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_title",
                                "PACKAGE": "com.android.car.settings.googlecarui.rro"
                        },
                        "CHOOSE_LOCK_TYPE": {
                                "TYPE": "TEXT",
                                "VALUE": "Choose a lock type"
                        },
                        "LOCK_TYPE_PASSWORD": {
                                "TYPE": "TEXT",
                                "VALUE": "Password"
                        },
                        "LOCK_TYPE_PIN": {
                                "TYPE": "TEXT",
                                "VALUE": "PIN"
                        },
                        "LOCK_TYPE_NONE": {
                                "TYPE": "TEXT",
                                "VALUE": "None"
                        },
                        "CONTINUE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Continue"
                        },
                        "CONFIRM_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Confirm"
                        },
                        "ENTER_PASSWORD": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        },
                        "PIN_PAD": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "pin_pad",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "ENTER_PIN_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "key_enter",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "REMOVE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Remove"
                        }
                }
        },
        "PHONE": {
                "APPLICATION_CONFIG": {
                        "DIAL_PACKAGE": "com.android.car.dialer",
                        "PHONE_ACTIVITY": "com.android.car.dialer/.ui.TelecomActivity",
                        "OPEN_DIAL_PAD_COMMAND": "am start -a android.intent.action.DIAL"
                },
                "IN_CALL_VIEW": {
                        "DIALED_CONTACT_TITLE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "user_profile_title",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "DIALED_CONTACT_NUMBER": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "user_profile_phone_number",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "END_CALL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "end_call_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "MUTE_CALL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "mute_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "SWITCH_TO_DIAL_PAD": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "toggle_dialpad_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CHANGE_VOICE_CHANNEL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "voice_channel_view",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "VOICE_CHANNEL_CAR": {
                                "TYPE": "TEXT",
                                "VALUE": "Car speakers"
                        },
                        "VOICE_CHANNEL_PHONE": {
                                "TYPE": "TEXT",
                                "VALUE": "Phone"
                        }
                },
                "DIAL_PAD_VIEW": {
                        "DIAL_PAD_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Dial Pad"
                        },
                        "DIAL_PAD_FRAGMENT": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "dialpad_fragment",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "DIALED_NUMBER": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "MAKE_CALL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "call_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "DELETE_NUMBER": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "delete_button",
                                "PACKAGE": "com.android.car.dialer"
                        }
                },
                "CONTACTS_VIEW": {
                        "CONTACTS_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Contacts"
                        },
                        "CONTACT_INFO": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "call_action_id",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_DETAIL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "show_contact_detail_id",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "ADD_CONTACT_TO_FAVORITE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "contact_details_favorite_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "SEARCH_CONTACT": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "menu_item_search",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_SEARCH_BAR": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_search_bar",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "SEARCH_RESULT": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "contact_name",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_SETTINGS": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "menu_item_setting",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_ORDER": {
                                "TYPE": "TEXT",
                                "VALUE": "Contact order"
                        },
                        "SORT_BY_FIRST_NAME": {
                                "TYPE": "TEXT",
                                "VALUE": "First name"
                        },
                        "SORT_BY_LAST_NAME": {
                                "TYPE": "TEXT",
                                "VALUE": "Last Name"
                        },
                        "CONTACT_TYPE_WORK": {
                                "TYPE": "TEXT",
                                "VALUE": "Work"
                        },
                        "CONTACT_TYPE_MOBILE": {
                                "TYPE": "TEXT",
                                "VALUE": "Mobile"
                        },
                        "CONTACT_TYPE_HOME": {
                                "TYPE": "TEXT",
                                "VALUE": "Home"
                        }
                },
                "CALL_HISTORY_VIEW": {
                        "CALL_HISTORY_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Recents"
                        },
                        "CALL_HISTORY_INFO": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "call_action_id",
                                "PACKAGE": "com.android.car.dialer"
                        }
                },
                "FAVORITES_VIEW": {
                        "FAVORITES_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Favorites"
                        }
                }
        },
        "NOTIFICATIONS": {
                "APPLICATION_CONFIG": {
                        "OPEN_NOTIFICATIONS_COMMAND": "service call statusbar 1"
                },
                "EXPANDED_NOTIFICATIONS_SCREEN": {
                        "NOTIFICATION_VIEW": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "notification_view",
                                "PACKAGE": "com.android.systemui"
                        },
                        "CLEAR_ALL_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "clear_all_button",
                                "PACKAGE": "com.android.systemui"
                        },
                        "STATUS_BAR": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_top_navigation_bar_container",
                                "PACKAGE": "com.android.systemui"
                        },
                        "APP_ICON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "app_icon",
                                "PACKAGE": "com.android.systemui"
                        },
                        "APP_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "header_text",
                                "PACKAGE": "com.android.systemui"
                        },
                        "NOTIFICATION_TITLE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "notification_body_title",
                                "PACKAGE": "com.android.systemui"
                        },
                        "NOTIFICATION_BODY": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "notification_body_content",
                                "PACKAGE": "com.android.systemui"
                        },
                        "CARD_VIEW": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "card_view",
                                "PACKAGE": "com.android.systemui"
                        }
                }
        },
        "MEDIA_CENTER": {
                "APPLICATION_CONFIG": {
                        "MEDIA_CENTER_PACKAGE": "com.android.car.media",
                        "MEDIA_ACTIVITY": "com.android.bluetooth/com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService"
                },
                "MEDIA_CENTER_SCREEN": {
                        "PLAY_PAUSE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "play_pause_stop",
                                "PACKAGE": "com.android.car.media"
                        },
                        "NEXT_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_next",
                                "PACKAGE": "com.android.car.media"
                        },
                        "PREVIOUS_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_prev",
                                "PACKAGE": "com.android.car.media"
                        },
                        "SHUFFLE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "overflow_on",
                                "PACKAGE": "com.android.car.media"
                        },
                        "PLAY_QUEUE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "play_queue",
                                "PACKAGE": "com.android.car.media"
                        },
                        "MINIMIZED_MEDIA_CONTROLS": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "minimized_playback_controls",
                                "PACKAGE": "com.android.car.media"
                        },
                        "TRACK_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.media"
                        },
                        "TRACK_NAME_MINIMIZED_CONTROL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "minimized_control_bar_title",
                                "PACKAGE": "com.android.car.media"
                        },
                        "BACK_BUTTON": {
                                "TYPE": "DESCRIPTION",
                                "VALUE": "Back"
                        }
                },
                "MEDIA_CENTER_ON_HOME_SCREEN": {
                        "PLAY_PAUSE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "play_pause_stop",
                                "PACKAGE": "com.android.car.carlauncher"
                        },
                        "NEXT_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_next",
                                "PACKAGE": "com.android.car.carlauncher"
                        },
                        "PREVIOUS_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_prev",
                                "PACKAGE": "com.android.car.carlauncher"
                        },
                        "TRACK_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.carlauncher"
                        }
                }
        }
}
  

Alternatywne konfiguracje urządzeń

Poniższy przykładowy kod przedstawia przykład pliku konfiguracyjnego JSON, w którym ustawienia domyślne są zastępowane przez ustawienia na urządzeniu DUT. W tym przykładzie:

  • Ustawienia internetowe noszą nazwy Sieć i Internet na urządzeniach referencyjnych oraz Łączność na urządzeniu DUT.

  • Ustawienia daty i godziny są dostępne w Ustawieniach > Data i godzina dla urządzeń referencyjnych oraz w Ustawienia > System > Data i godzina dla testowanego urządzenia.

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

Gdy plik konfiguracyjny JSON jest gotowy, jest udostępniany w czasie wykonywania, jak pokazano w następującym bloku kodu:

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

W tym poleceniu:

  • DEVICE-SERIAL : Identyfikator seryjny testowanego urządzenia. Parametr ten nie jest wymagany, jeśli do hosta podłączone jest tylko jedno urządzenie.

  • PATH-TO-JSON-FILE : Ścieżka pliku JSON na komputerze hosta.

Format konfiguracji

W konfiguracji znajduje się pięć obiektów najwyższego poziomu z następującymi kluczami i wartościami:

Obiekt Opis
PACKAGES Obiekt opisujący główny pakiet różnych aplikacji, który służy do określenia, kiedy dana aplikacja znajduje się na pierwszym planie.
ACTIONS Obiekt wskazujący typy akcji i parametry dla różnych akcji. Na przykład, czy do przewijania używać przycisków, czy gestów.
COMMANDS Obiekt określający polecenia wykonujące różne akcje.
UI_ELEMENTS Obiekt używany do konstruowania automatora interfejsu użytkownika „BySelectors”, który wybiera elementy interfejsu użytkownika (opisane szczegółowo poniżej).
WORKFLOWS Sekwencje działań realizujące zadania wysokiego poziomu (opisane szczegółowo poniżej).

Elementy interfejsu użytkownika

Każdy element interfejsu użytkownika ma TYPE , który określa, czego Automator interfejsu użytkownika będzie szukać, aby zidentyfikować element (np. identyfikator zasobu, tekst i opis) oraz wartości konfiguracyjne powiązane z tym typem. Ogólnie rzecz biorąc, ilekroć pomocnik zidentyfikuje element na ekranie przy użyciu tej konfiguracji, otrzymuje dokładnie jeden element. Jeżeli do konfiguracji pasuje wiele elementów, w teście używany jest dowolny. Dlatego konfiguracja powinna (zazwyczaj) być napisana na tyle szczegółowo, aby zawęzić ją do jednego elementu w odpowiednim kontekście.

TEKST

Jest to najprostszy typ elementu interfejsu użytkownika. Element interfejsu użytkownika jest identyfikowany przez tekst i wymaga dokładnego dopasowania.

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

TEXT_CONTAINS

To samo co TEXT , z tą różnicą, że określona VALUE musi jedynie pojawić się gdzieś w tekście elementu, który ma zostać dopasowany.

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

OPIS

Zidentyfikuj element na podstawie jego atrybutu opisu zawartości, co wymaga dokładnego dopasowania.

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

Identyfikator Zasobu

Zidentyfikuj element na podstawie jego identyfikatora zasobu, opcjonalnie sprawdzając także komponent pakietu o tym identyfikatorze. Klawisz PACKAGE jest opcjonalny; jeśli zostanie pominięty, każdy pakiet będzie pasował i tylko część identyfikatora następująca po :id/ będzie brana pod uwagę.

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

KLIKALNE, PRZEWIJANE

Zidentyfikuj element na podstawie tego, czy można go kliknąć lub przewijać (czy nie). Są to bardzo szerokie typy elementów i generalnie powinny być używane tylko w MULTIPLE , aby pomóc zawęzić zakres innego typu elementu. Klawisz FLAG jest opcjonalny i domyślnie ma wartość true .

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

KLASA

Zidentyfikuj element na podstawie jego klasy.

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

HAS_ANCESTOR

Zidentyfikuj element, przeglądając hierarchię widżetów pod kątem jego przodków. Klucz ANCESTOR przechowuje obiekt identyfikujący przodka. Klawisz DEPTH określa, jak wysoko w hierarchii należy szukać. DEPTH jest opcjonalna i ma wartość domyślną 1 .

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

HAS_DESCENDANT

Zidentyfikuj element, patrząc w dół hierarchii na jego dzieci. Klucz DESCENDANT przechowuje obiekt określający dziecko, którego należy szukać. Klawisz DEPTH określa, jak wysoko w hierarchii należy szukać. DEPTH jest opcjonalna i ma wartość domyślną 1 .

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

WIELE

Zidentyfikuj element na podstawie wielu jednoczesnych warunków, z których wszystkie muszą być spełnione.

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

W tym przykładzie konfiguracja identyfikuje RelativeLayout , który ma element potomny na głębokości 2 i który zawiera tekst Permission manager .

Przepływy pracy

Przepływ pracy reprezentuje sekwencję działań używanych do wykonania określonego zadania, która może różnić się w zależności od typu urządzenia i jest bardziej elastyczna do przedstawienia w konfiguracji niż w kodzie.

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

Każdy przepływ pracy to para klucz-wartość, gdzie klucz to nazwa przepływu pracy, a wartość to tablica działań do wykonania. Każda akcja ma NAME , TYPE , (zwykle) CONFIG i (czasami) SWIPE_CONFIG lub SCROLL_CONFIG . Dla większości TYPÓW CONFIG jest obiektem z kluczem UI_ELEMENT , którego wartość przyjmuje taką samą formę jak wpis elementu UI (patrz wyżej). Te TYPY to:

NACISKAĆ
LONG_PRESS
KLIKNIJ
LONG_CLICK
KLIKNIJ_IF_ISTNIEJE
HAS_UI_ELEMENT_IN_FOREGROUND
SCROLL_TO_FIND_AND_KLIKNIJ
SCROLL_TO_FIND_AND_CLICK_IF_EXIST
PRZESUŃ_TO_FIND_AND_KLIKNIJ
PRZESUŃ_TO_FIND_AND_CLICK_IF_EXIST

W przypadku pozostałych TYPÓW szczegóły konfiguracji są następujące:

Obiekt Opis
COMMAND Obiekt z wartością TEXT zawierającą polecenie do wykonania.
HAS_PACKAGE_IN_FOREGROUND Obiekt z wartością TEXT zawierającą pakiet.
SWIPE Pomiń CONFIG key dla akcji SWIPE . Używa tylko SWIPE_CONFIG
WAIT_MS Obiekt z wartością TEXT zawierającą liczbę milisekund oczekiwania.

Działania związane z przewijaniem i przesuwaniem wymagają dodatkowej konfiguracji w następujący sposób:

SCROLL_CONFIG

Obiekt Opis
SCROLL_ACTION Albo USE_GESTURE , albo USE_BUTTON
SCROLL_DIRECTION HORIZONTAL lub VERTICAL
SCROLL_ELEMENT Obiekt wskazujący kontener do przewijania, przy użyciu tej samej formy co konfiguracja elementu interfejsu użytkownika (patrz wyżej).
SCROLL_FORWARD , SCROLL_BACKWARD Przyciski przewijania do przodu i do tyłu (wymagane, gdy SCROLL_ACTION ma USE_BUTTON ).
SCROLL_MARGIN Jeśli SCROLL_ACTION to USE_GESTURE , jest to odległość od krawędzi kontenera, na której rozpoczyna się i kończy przeciąganie, która będzie używana podczas przewijania ( opcjonalnie, domyślnie = 10).
SCROLL_WAIT_TIME Jeśli SCROLL_ACTION to USE_GESTURE , czas w milisekundach oczekiwania pomiędzy gestami przewijania podczas wyszukiwania obiektu do kliknięcia. ( Opcjonalnie, domyślnie = 1).

PRZESUŃ_KONFIG

Obiekt Opis
SWIPE_DIRECTION Albo TOP_TO_BOTTOM , BOTTOM_TO_TOP , LEFT_TO_RIGHT , albo RIGHT_TO_LEFT
SWIPE_FRACTION

Jeden z następujących:

  • FULL : Gest przesunięcia od krawędzi ekranu do krawędzi ekranu

    LUB,
  • DEFAULT : Od krawędzi do krawędzi ekranu, z buforem pięciu (5) pikseli po każdej stronie.

    LUB,
  • THREE_QUARTER , HALF lub QUARTER : Gest przeciągnięcia kończy się pięć (5) pikseli od krawędzi ekranu i rozpoczyna się w punkcie obejmującym wskazaną odległość ekranu.
NUMBER_OF_STEPS Liczba kroków, które należy wykonać, aby wykonać przesunięcie. Zobacz segmentSteps .

Buduj i wykonuj

Framework Spectatio jest tworzony automatycznie jako część testowego pliku APK. Aby zbudować testowy plik APK, baza kodu AOSP musi znajdować się na lokalnej stacji roboczej. Po zbudowaniu testowego pakietu APK użytkownik musi zainstalować plik APK na urządzeniu i przeprowadzić test.

Poniższy przykładowy kod przedstawia tworzenie, instalację i wykonanie testowego pakietu 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

W tych poleceniach:

  • TEST-APK-NAME : Nazwa aplikacji, która ma być testowana. Na przykład ustaw TEST-APK-NAME na AndroidAutomotiveSettingsTests , aby przetestować ustawienia Wi-Fi określone w pliku Android.bp . Nazwę pakietu APK można znaleźć w odpowiednim pliku Android.bp dla testu samochodowego .

  • DEVICE-SERIAL : Identyfikator seryjny urządzenia DUT. Ten parametr nie jest wymagany, jeśli do hosta podłączone jest tylko jedno urządzenie.

  • config-file-path : parametr opcjonalny, który jest wymagany tylko w celu zapewnienia konfiguracji interfejsu użytkownika urządzenia innych niż domyślne, jak określono w pliku konfiguracyjnym JSON . Jeśli nie zostanie podany, platforma używa wartości domyślnych do wykonywania testów.

  • PATH-FOR-BUILT-TEST-APK : Ścieżka, w której tworzony jest testowy plik APK po wykonaniu polecenia make .

  • TEST-PACKAGE : Nazwa pakietu testowego.

  • TEST-CLASSNAME : Nazwa klasy testowej. Na przykład w przypadku testu ustawień Wi-Fi pakiet testowy to android.platform.tests , a nazwa klasy testowej to WifiSettingTest .

Biblioteka fragmentów motoryzacyjnych

Biblioteka fragmentów motoryzacyjnych to zestaw bibliotek testowych systemu Android dla projektu Android Open Source Project (AOSP), zaprojektowanych do interakcji z aplikacjami i usługami motoryzacyjnymi. Wykorzystuje Spectatio z wygodnym mechanizmem wykonywania zdalnych wywołań procedur (RPC) z komputera hosta (testowego) na urządzenie z systemem Android.

Zaczynaj

Zanim zaczniesz, przejrzyj te sekcje.

Warunki wstępne

  • Python 3.x zainstalowany na komputerze hosta.
  • Konfiguracja środowiska AOSP z niezbędnymi narzędziami do kompilacji.
  • Urządzenie samochodowe z systemem Android (emulator lub urządzenie fizyczne) z dostępem adb.

Kompilacja

Aby skompilować różne fragmenty dostarczone przez Automotive Snippet Library, możesz użyć dostarczonego pliku android.bp . Wykonaj polecenia z poprzedniej sekcji, aby skompilować plik APK.

Zastosowanie

Po pomyślnym skompilowaniu bibliotek fragmentów wdróż powstałe pliki APK na urządzeniu docelowym za pomocą polecenia adb install wspomnianego w poprzedniej sekcji.

Uruchom testy

Biblioteki fragmentów udostępniają kilka metod RPC umożliwiających interakcję z systemem motoryzacyjnym. Metody te można wywołać za pośrednictwem platformy Mobly z komputera hosta. Zakładając, że masz skonfigurowane środowisko testowe Mobly, możesz użyć skryptu snippet_shell.py , aby otworzyć interaktywną powłokę Pythona, w której możesz ręcznie wywoływać metody RPC na urządzeniu. Przykładowe wywołanie:

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

Zastąp <serial> numerem seryjnym urządzenia, który można uzyskać za pomocą urządzeń adb, jeśli podłączonych jest wiele urządzeń.

Dołączone biblioteki

Biblioteka fragmentów motoryzacyjnych zawiera następujące biblioteki fragmentów i pomocników:

  • AutomotiveSnippet: udostępnia interfejsy API związane z operacjami pojazdu, takimi jak wybieranie numerów, regulacja głośności, klawisze stałe pojazdu i interakcja z centrum multimedialnym.

  • PhoneSnippet: udostępnia interfejsy API związane z telefonią, w tym obsługę połączeń, przeglądanie kontaktów i operacje SMS.

Fragment Automotive i PhoneSnippet mają wspólną logikę. W szczególności możesz atakować połączenia RCP związane z Bluetooth, aby sparować samochód z urządzeniem telefonicznym. Ten bt_discovery_test pokazuje, jak to zrobić.