Spectatio: platforma do testów motoryzacyjnych

Spectatio to platforma testowa typu open source opracowana do testowania systemu operacyjnego Android Automotive (AAOS) na urządzeniach rzeczywistych i wirtualnych. Spectatio udostępnia interfejsy API do testowania aplikacji na urządzeniu samochodowym. Jest to rozszerzalne i skalowalne rozwiązanie służące do weryfikowania możliwości i wydajności AAOS oraz jego aplikacji.

Projektowanie ogólne

Platforma Spectatio jest elastyczna i można ją rozszerzać, aby implementować różne interfejsy AAOS. Służy do testowania możliwości i wydajności AAOS na sprzęcie, emulatorach i wirtualizowanych środowiskach.

Na rysunku poniżej przedstawiono ogólną strukturę platformy Spectatio.

Ogólny projekt platformy Spectatio

Rysunek 1. Ogólny projekt platformy Spectatio.

Platforma Spectatio oparta na UI Automator udostępnia zestaw interfejsów API do tworzenia testów interfejsu użytkownika, które współpracują z aplikacjami użytkownika i systemowymi na AAOS. Testy dotyczące pojazdów korzystają z interfejsów API udostępnianych przez platformę Spectatio, dzięki czemu są niezależne od testowanego urządzenia i można je skalować na różne urządzenia (jeśli są obsługiwane).

Jak widać na rysunku 1, platforma Spectatio jest podzielona na moduły na podstawie aplikacji referencyjnych, takich jak Dialer, Medicenter i Settings, z użyciem interfejsów i elementów pomocniczych do konkretnych aplikacji, co ułatwia rozszerzanie platformy o nowe aplikacje. Framework Spectatio używa ponownie standardowych klas pomocniczych i klas pomocniczych do obsługi. Standardowa klasa pomocnicza jest klasą nadrzędną dla wszystkich funkcji pomocniczych aplikacji i zawiera standardowe funkcje, które są specyficzne dla urządzenia lub mają zastosowanie w różnych aplikacjach. Klasy pomocnicze zapewniają takie funkcje, jak odczytywanie i zapisywanie plików z urządzenia.

Architektura

Aby udostępnić zestaw interfejsów API do tworzenia testów interfejsu, platforma Spectatio implementuje interfejsy i elementy pomocnicze przeznaczone dla konkretnych aplikacji, jednocześnie rozszerzając istniejącą standardową klasę pomocniczą i importując klasy pomocnicze.

Rysunek 2 przedstawia ogólną architekturę platformy Spectatio i wszystkie podmioty zaangażowane w implementację interfejsów API do testowania aplikacji.

Architektura ogólna platformy Spectatio

Rysunek 2. Architektura ogólna platformy Spectatio

Interfejs pomocy w aplikacji zawiera szablon implementacji pomocy w aplikacji. Składa się on z różnych funkcji pomocniczych, które są potrzebne do testowania aplikacji. Każda aplikacja ma własny interfejs, np. IAutoSettingHelper i IAutoDialHelper. Więcej informacji oraz listę funkcji interfejsu znajdziesz w artykule o funkcjach interfejsu Asystenta aplikacji w AOSP.

Standardowa klasa pomocnicza składa się ze standardowych atrybutów i funkcji, które są wymagane do konfiguracji urządzenia, ale nie są specyficzne dla żadnej aplikacji, takich jak pressHomescroll. Standardowa klasa pomocnicza jest zdefiniowana w AbstractAutoStandardAppHelper.java.

Platforma używa klas pomocniczych narzędzi. Na przykład AutoJsonUtility.java jest klasą narzędziową, która wczytuje plik konfiguracji JSON danego urządzenia i aktualizuje konfiguracje platformy w czasie działania.

Moduł implementacji pomocy aplikacji jest podstawą platformy Spectatio. Zawiera on implementację funkcji pomocniczych zdefiniowanych w interfejsie aplikacji, które są wymagane do testowania aplikacji na urządzeniu samochodowym. Każda aplikacja ma własną implementację, np. SettingHelperImpl i DialHelperImpl, która jest używana przez testy Automotive do testowania aplikacji. Więcej informacji i listę implementacji znajdziesz w funkcjach implementacji pomocy aplikacji w AOSP.

Testy motoryzacyjne korzystają z funkcji implementacji pomocy aplikacji, aby testować różne operacje związane z aplikacją. Aby uzyskać dostęp do funkcji implementacji pomocy aplikacji, użyj klasy HelperAccessor.

Poniżej znajduje się kod, który przedstawia konfigurację, czyszczenie i wykonanie przykładowego testu motoryzacyjnego.

@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

Platforma Spectatio jest niezależna od interfejsu użytkownika urządzenia, dzięki czemu można ją skalować do testowania urządzeń z różnymi interfejsami i sprzętem. Aby zapewnić taką skalowalność, Spectatio używa domyślnych konfiguracji urządzeń na podstawie urządzenia referencyjnego. Aby obsługiwać konfiguracje urządzeń inne niż domyślne, framework używa pliku konfiguracji JSON w czasie wykonywania, aby wprowadzać na urządzeniu zmiany interfejsu użytkownika. Plik konfiguracji JSON obsługuje elementy interfejsu użytkownika, takie jak TEXT, DESCRIPTIONRESOURCE_ID, a także ustawienia path. Musi zawierać tylko informacje o zmianach interfejsu użytkownika w przypadku DUT. Pozostałe elementy interfejsu użytkownika korzystają z domyślnych wartości konfiguracji podanych w ramach.

Domyślne konfiguracje urządzenia

Poniższy przykładowy plik konfiguracji JSON zawiera dostępne konfiguracje urządzenia i ich wartości domyślne.

Kliknij tutaj, aby wyświetlić przykładowy plik konfiguracji 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 pokazuje plik konfiguracji JSON, w którym ustawienia domyślne są zastępowane przez ustawienia na urządzeniu testowym. W tym przykładzie:

  • Ustawienia internetu mają nazwę Sieć i internet na urządzeniach referencyjnych oraz Łączność na urządzeniu testowym.

  • Ustawienia daty i godziny są dostępne w sekcji Ustawienia > Data i godzina na urządzeniach referencyjnych oraz w sekcji Ustawienia > System > Data i godzina na urządzeniu testowanym.

// 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 konfiguracji JSON jest gotowy, jest on udostępniany w czasie wykonywania, jak pokazano w tym 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 urządzenia pokładowego (DUT). Ten parametr nie jest wymagany, jeśli z hostem połączone jest tylko jedno urządzenie.

  • PATH-TO-JSON-FILE: ścieżka pliku JSON na hoście.

Format konfiguracji

W konfiguracji jest 5 obiektów najwyższego poziomu z tymi kluczami i wartościami:

Obiekt Opis
PACKAGES Obiekt opisujący główny pakiet różnych aplikacji, który służy do określania, kiedy aplikacja jest na pierwszym planie.
ACTIONS Obiekt określający typy i parametry różnych działań. Na przykład czy do przewijania ma służyć przycisk czy gest.
COMMANDS Obiekt określający polecenia wykonujące różne działania.
UI_ELEMENTS Obiekt używany do tworzenia automatyzacji interfejsu użytkownika „BySelectors”, która wybiera elementy interfejsu (opisane szczegółowo poniżej).
WORKFLOWS Sekwencje działań, które wykonują zadania ogólne (opisane szczegółowo poniżej).

Elementy interfejsu

Każdy element interfejsu użytkownika ma atrybuty TYPE, które określają, czego UI Automator będzie szukać, aby zidentyfikować element (np. identyfikator zasobu, tekst i opis), oraz wartości konfiguracji powiązane z tym typem. Ogólnie rzecz biorąc, gdy pomocnik rozpoznaje element na ekranie za pomocą tej konfiguracji, wybiera dokładnie jeden element. Jeśli konfiguracja pasuje do wielu elementów, w teście zostanie użyty dowolny z nich. Dlatego konfiguracja powinna być napisana na tyle specjalnie, by w odpowiednim kontekście zawężała się do jednego elementu.

TEKST

Jest to najprostszy typ elementu interfejsu. Element interfejsu użytkownika jest identyfikowany na podstawie tekstu i wymaga dopasowania ścisłego.

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

TEXT_CONTAINS

To samo co TEXT, z tą różnicą, że określone wyrażenie VALUE musi się tylko pojawić w tekście elementu, do którego ma być dopasowane.

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

OPIS

Identyfikować element za pomocą atrybutu opisu treści, wymagając dokładnego dopasowania.

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

IDENTYFIKATOR_ZASOBU

Identyfikuj element według jego identyfikatora zasobu, opcjonalnie sprawdzając też komponent pakietu tego identyfikatora. Klucz PACKAGE jest opcjonalny. W przypadku jego pominięcia dowolny pakiet będzie dopasowywany i tylko część identyfikatora po :id/ będzie brana pod uwagę.

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

MOŻLIWOŚĆ KLIKANIA I PRZEWIJANIA

Określ, czy element można kliknąć lub przewinąć. Są to bardzo ogólne typy elementów. Zazwyczaj należy ich używać w elemencie MULTIPLE, aby zawężać zakres innego typu elementów. Klucz FLAG jest opcjonalny i domyślnie ma wartość true.

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

CLASS

Identyfikuj element na podstawie jego klasy.

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

HAS_ANCESTOR

Aby go zidentyfikować, sprawdź hierarchię widżetów na poziomie ich przodków. Klucz ANCESTOR zawiera obiekt, który identyfikuje przodka. Klucz DEPTHokreśla, jak daleko w hierarchii mają być wyszukiwane dane. Opcjonalne pole DEPTH ma domyślną wartość 1.

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

HAS_DESCENDANT

Identyfikuj element, przeglądając hierarchię w dół, czyli elementy podrzędne. Klucz DESCENDANT zawiera obiekt, który wskazuje obiekt podrzędny do wyszukania. Klucz DEPTH określa, jak daleko w hierarchii należy się patrzeć. Parametr DEPTH jest opcjonalny i ma domyślną wartość 1.

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

WIELE

Określ element na podstawie wielu warunków, które 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 wskazuje element RelativeLayout, który ma potomka na poziomie 2, zawierający tekst Permission manager.

Workflows

Proces to sekwencja działań służących do wykonania określonego zadania, która może się znacznie różnić w zależności od typu urządzenia. Procesy są bardziej elastyczne w użyciu 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 kluczem jest nazwa przepływu pracy, a wartością – tablica działań do wykonania. Każde działanie ma NAME, TYPE, (zwykle) CONFIG, a czasami SWIPE_CONFIG lub SCROLL_CONFIG. W przypadku większości typów TYPE CONFIG jest obiektem z kluczem UI_ELEMENT, którego wartość ma taką samą postać jak wpis elementu interfejsu (patrz wyżej). Typy:

PRESS
LONG_PRESS
CLICK
LONG_CLICK
CLICK_IF_EXIST
HAS_UI_ELEMENT_IN_FOREGROUND
PRZEWIŃ_DO_ZNAJDŹ_ORAZ_KLIKNIĘCIE
SCROLL_TO_FIND_AND_CLICK_IF_EXIST
PRZEWIŃ_TO_ZNAJDŹ_ORAZ_KLIKNIJ
SSTORAGE_TO_FIND_AND_KLIKNIJ_IF_EXIST

W przypadku innych typów szczegóły konfiguracji to:

Obiekt Opis
COMMAND Obiekt z wartością TEXT zawierającą polecenie do wykonania.
HAS_PACKAGE_IN_FOREGROUND Obiekt z wartością TEXT zawierający pakiet.
SWIPE Pomiń CONFIG key w przypadku działania SWIPE. Wykorzystuje 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:

PRZEWIŃ_KONFIGURACJĘ

Obiekt Opis
SCROLL_ACTION Może to być USE_GESTURE lub USE_BUTTON.
SCROLL_DIRECTION Może to być HORIZONTAL lub VERTICAL.
SCROLL_ELEMENT Obiekt wskazujący kontener, który ma być przewijany. Obiekt ma tę samą formę co konfiguracja elementu interfejsu (patrz wyżej).
SCROLL_FORWARD, SCROLL_BACKWARD przyciski przewijania do przodu i do tyłu (wymagane, gdy SCROLL_ACTION = USE_BUTTON);
SCROLL_MARGIN Jeśli SCROLL_ACTION to USE_GESTURE, odległość od krawędzi kontenera do rozpoczęcia i zatrzymania przeciągania, po którym zostanie przewijane (opcjonalne, wartość domyślna = 10).
SCROLL_WAIT_TIME Jeśli SCROLL_ACTION to USE_GESTURE, czas w milisekundach, przez jaki należy czekać między gestami przewijania podczas wyszukiwania obiektu do kliknięcia. (Opcjonalne,wartość domyślna = 1).

SWIPE_CONFIG

Obiekt Opis
SWIPE_DIRECTION Może to być TOP_TO_BOTTOM, BOTTOM_TO_TOP, LEFT_TO_RIGHT lub RIGHT_TO_LEFT
SWIPE_FRACTION

Wykonaj jedną z tych czynności:

  • FULL: przesuń palcem od krawędzi do krawędzi ekranu

    LUB,
  • DEFAULT: od krawędzi do krawędzi ekranu z buforem 5 pikseli po każdej stronie.

    LUB
  • THREE_QUARTER, HALF lub QUARTER: gest przesuwania kończy się o pięć (5) pikseli od krawędzi ekranu i zaczyna się w punkcie, który zajmuje wskazówkę na odległość.
NUMBER_OF_STEPS Liczba kroków, które mają być wykonane podczas przesuwania. Zobacz segmentSteps.

Tworzenie i wykonywanie

Platforma Spectatio jest tworzona automatycznie jako część testowego pakietu APK. Aby skompilować testowy plik APK, kod źródłowy AOSP musi znajdować się na lokalnej stacji roboczej. Po skompilowaniu testowego pliku APK użytkownik musi zainstalować go na urządzeniu i przeprowadzić test.

Poniższy przykładowy kod pokazuje kompilowanie, instalowanie i uruchamianie testowego pliku 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 zostać przetestowana. Na przykład ustaw TEST-APK-NAME na AndroidAutomotiveSettingsTests, aby przetestować ustawienia Wi-Fi zgodnie z danymi w pliku Android.bp. Nazwę pakietu APK znajdziesz w odpowiednim pliku Android.bp dotyczącym testu samochodowego.

  • DEVICE-SERIAL: numer seryjny DUT. Ten parametr nie jest wymagany, jeśli z hostem jest połączone tylko jedno urządzenie.

  • config-file-path: opcjonalny parametr wymagany tylko do udostępniania niestandardowych konfiguracji interfejsu użytkownika urządzenia zgodnie z opisem w pliku konfiguracji JSON. Jeśli nie podasz wartości, framework użyje wartości domyślnych do wykonania testów.

  • PATH-FOR-BUILT-TEST-APK: ścieżka tworzenia testowego pakietu APK po wykonaniu polecenia make.

  • TEST-PACKAGE: nazwa pakietu testowego.

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

Biblioteka fragmentów dotyczących motoryzacji

Automotive Snippet Library to zestaw bibliotek Android Test dla projektu Android Open Source (AOSP) zaprojektowanych do interakcji z aplikacją i usługami samochodowymi. Korzysta on z narzędzia Spectatio, które zapewnia wygodny mechanizm wykonywania wywołań procedur zdalnych (RPC) z hosta (maszyny testowej) na urządzenie z Androidem.

Rozpocznij

Zanim zaczniesz, zapoznaj się z tymi sekcjami.

Wymagania wstępne

  • Python 3.x zainstalowany na komputerze hosta.
  • Konfiguracja środowiska AOSP z wymaganymi narzędziami do kompilacji.
  • Urządzenie z Androidem Automotive (emulator lub urządzenie fizyczne) z dostępem do adb.

Kompilacja

Aby skompilować różne fragmenty kodu udostępnione przez Automotive Snippet Library, możesz użyć dostarczonego pliku android.bp. Użyj poleceń z poprzedniej sekcji, aby skompilować plik APK.

Wdrażanie

Po skompilowaniu bibliotek fragmentów wdróż utworzone pliki APK na urządzeniu docelowym za pomocą polecenia adb install wymienionego w poprzedniej sekcji.

Przeprowadzanie testów

Biblioteki fragmentów kodu udostępniają kilka metod RPC do interakcji z systemem samochodowym. Te metody można wywołać za pomocą frameworka Mobly z maszyny 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ład wywołania:

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

Zastąp <serial> numerem seryjnym urządzenia, który możesz uzyskać za pomocą ADB devices, jeśli masz podłączone większą liczbę urządzeń.

Uwzględnione biblioteki

Biblioteka fragmentów kodu samochodowego zawiera następujące biblioteki fragmentów i funkcje pomocnicze:

  • AutomotiveSnippet: udostępnia interfejsy API związane z obsługą pojazdu, takie jak wybieranie numerów, sterowanie głośnością, przyciski w samochodzie i interakcje 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 kodu Automotive i fragment kodu PhoneSnippet mają wspólną logikę. W szczególności możesz w ten sposób wtrącać się w wywołania RCP związane z Bluetooth, aby sparować urządzenie samochodowe z telefonem. Więcej informacji znajdziesz w artykule bt_discovery_test.