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 weryfikacji możliwości i wydajności AAOS oraz jego aplikacji.

Projektowanie na wysokim poziomie

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 w wirtualnych ś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 aplikacją użytkownika i aplikacją systemową 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 dostępnych w przypadku poszczególnych 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 utility helper zapewniają takie funkcje, jak odczytywanie i zapisywanie plików z urządzenia.

Architektura

Aby zapewnić zestaw interfejsów API do tworzenia testów interfejsu użytkownika, framework Spectatio implementuje interfejsy i elementy pomocnicze związane z konkretną aplikacją, rozszerzając istniejące standardowe klasy pomocnicze oraz importując pomocnicze klasy pomocnicze.

Rysunek 2 przedstawia ogólną architekturę platformy Spectatio oraz wszystkie elementy zaangażowane w wdrażanie interfejsów API do testowania aplikacji.

Architektura ogólna platformy Spectatio

Rysunek 2. Architektura ogólna platformy Spectatio

Interfejs aplikacji pomocniczej zawiera szablon implementacji aplikacji pomocniczej. 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 i listę funkcji interfejsu znajdziesz w funkcjach interfejsu pomocnika 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.

Framework korzysta z klas pomocniczych. Na przykład AutoJsonUtility.java to klasa pomocnicza, która wczytuje plik konfiguracji JSON danego urządzenia i aktualizuje konfiguracje platformy w czasie wykonywania.

Moduł implementacji pomocy aplikacji jest podstawą platformy Spectatio. Zawiera implementację funkcji pomocniczych zdefiniowanych w interfejsie pomocniczym aplikacji, które są wymagane do testowania aplikacji na urządzeniu samochodowym. Każda aplikacja ma własne wdrożenie, np. SettingHelperImpl i DialHelperImpl, które są używane 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 aplikacji pomocniczej do testowania różnych operacji związanych z aplikacją. Aby uzyskać dostęp do funkcji implementacji aplikacji pomocniczej, użyj klasy HelperAccessor.

Poniższy kod pokazuje konfigurację, sprzątanie 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

Platforma Spectatio jest niezależna od interfejsu użytkownika urządzenia, dzięki czemu można ją skalować na potrzeby 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 w czasie wykonywania pliku konfiguracyjnego JSON do wprowadzania na urządzeniu odpowiednich zmian w interfejsie 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: numer seryjny urządzenia DUT. Ten parametr nie jest wymagany, jeśli z hostem połączone jest tylko jedno urządzenie.

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

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ć (ogółem) na tyle szczegółowa, aby zawężać ją do jednego elementu w odpowiednim kontekście.

TEKST

Jest to najprostszy typ elementu interfejsu. Element interfejsu użytkownika jest identyfikowany przez tekst 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 VALUE musi się tylko pojawić w tekście elementu, do którego ma być dopasowany.

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

OPIS

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

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

RESOURCE_ID

Identyfikuj element za pomocą jego identyfikatora zasobu, opcjonalnie sprawdzając również komponent pakietu tego identyfikatora. Klucz PACKAGE jest opcjonalny. Jeśli go pominiesz, pasować będzie dowolny pakiet, a uwzględniona zostanie tylko część identyfikatora po :id/.

    "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 i zwykle należy ich używać tylko w elemencie MULTIPLE, aby zawęzić zakres innego typu elementu. Klucz FLAG jest opcjonalny i domyślnie ma wartość true.

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

CLASS

Określ element na podstawie jego klasy.

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

HAS_ANCESTOR

Identyfikuj element, wyszukując hierarchię widżetów w ich przodkach. 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 określa element podrzędny do wyszukania. Klucz DEPTH określa, jak daleko w hierarchii należy szukać. 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, i zawiera 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żda czynność ma NAME, TYPE, (zwykle) CONFIG i (czasami) SWIPE_CONFIG lub SCROLL_CONFIG. W przypadku większości typów CONFIG to obiekt z kluczem UI_ELEMENT, którego wartość ma tę samą postać co wpis elementu interfejsu użytkownika (patrz wyżej). Typy:

PRESS
LONG_PRESS
CLICK
LONG_CLICK
CLICK_IF_EXIST
HAS_UI_ELEMENT_IN_FOREGROUND
SCROLL_TO_FIND_AND_CLICK
SCROLL_TO_FIND_AND_CLICK_IF_EXIST
SWIPE_TO_FIND_AND_CLICK
SWIPE_TO_FIND_AND_CLICK_IF_EXIST

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

Obiekt Opis
COMMAND Obiekt o wartości TEXT zawierający polecenie do wykonania.
HAS_PACKAGE_IN_FOREGROUND Obiekt z wartością TEXT zawierający pakiet.
SWIPE Pomiń CONFIG key w przypadku działania SWIPE. Ten eksperyment używa tylko SWIPE_CONFIG
WAIT_MS Obiekt z wartością TEXT zawierającą liczbę milisekund oczekiwania.

Czynności związane z przewijaniem i przesuwaniem wymagają dodatkowej konfiguracji:

SCROLL_CONFIG

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, przy użyciu tego samego formularza co konfiguracja elementu interfejsu (patrz powyż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 punktu początkowego i końcowego przeciągania, który będzie używany do przewijania (opcjonalnie, domyślnie = 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, domyślnie = 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 przesunięcia kończy się 5 pikseli od krawędzi ekranu i rozpoczyna się w takim miejscu, aby obejmować wskazaną odległość na ekranie.
NUMBER_OF_STEPS Liczba kroków, które mają być wykonane podczas przesuwania. Zobacz segmentSteps.

Tworzenie i wykonywanie

Framework Spectatio jest automatycznie kompilowany w ramach pliku APK testowego. 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 tym, co jest określone w pliku Android.bp. Nazwa pliku APK znajduje się w odpowiednim pliku Android.bp testu motoryzacyjnego.

  • DEVICE-SERIAL: numer seryjny DUT. Ten parametr nie jest wymagany, jeśli z hostem połączone jest 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, na której budowany jest testowy plik APK, gdy wykonywane jest polecenie 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 dla branży motoryzacyjnej zawiera te biblioteki fragmentów kodu i elementy 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 wkradać się do wywołań RCP związanych z Bluetooth, aby sparować urządzenie samochodowe z telefonem. Więcej informacji znajdziesz w artykule bt_discovery_test.