Spectatio to platforma testowa typu open source opracowana do testowania systemu operacyjnego Android Automotive (AAOS) na rzeczywistych i wirtualnych urządzeniach. 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.
Projekt wysokiego poziomu
Platforma Spectatio jest elastyczna i można ją rozbudowywać w celu obsługi różnych implementacji interfejsu AAOS. Służy do testowania możliwości i wydajności AAOS na sprzęcie urządzenia, emulatorach i w środowiskach wirtualnych.
Na rysunku poniżej przedstawiono ogólną strukturę 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, które wchodzą w interakcje z aplikacjami użytkownika i systemowymi w AAOS. Testy Automotive korzystają z interfejsów API udostępnianych przez platformę Spectatio, co sprawia, że są one niezależne od testowanego urządzenia i można je skalować, aby testować różne urządzenia, jeśli są one obsługiwane.
Na rysunku 1 widać, że platforma Spectatio jest podzielona na moduły na podstawie aplikacji referencyjnych, takich jak Dialer, Medicenter i Ustawienia, które korzystają z interfejsów i funkcji pomocniczych specyficznych dla aplikacji, co ułatwia rozszerzanie platformy o nowe aplikacje. Platforma Spectatio ponownie wykorzystuje standardowe i pomocnicze klasy narzędziowe. Standardowa klasa pomocnicza jest klasą nadrzędną dla wszystkich funkcji pomocniczych aplikacji i zapewnia standardowe funkcje, które są specyficzne dla urządzenia lub mają zastosowanie w różnych aplikacjach. Klasy narzędziowe udostępniają narzędzia, takie jak odczytywanie i zapisywanie plików na urządzeniu.
Architektura
Aby udostępnić zestaw interfejsów API do tworzenia testów interfejsu, platforma Spectatio implementuje interfejsy i funkcje pomocnicze specyficzne dla aplikacji, rozszerzając istniejącą standardową klasę funkcji pomocniczych i importując klasy funkcji pomocniczych narzędzi.
Rysunek 2 przedstawia ogólną architekturę platformy Spectatio i wszystkie podmioty zaangażowane we wdrażanie interfejsów API do testowania aplikacji.
Rysunek 2. Architektura wysokiego poziomu platformy Spectatio.
Interfejs pomocnika aplikacji zawiera plan wdrożenia pomocnika aplikacji. Zawiera różne funkcje pomocnicze potrzebne do testowania aplikacji. Każda aplikacja ma własny interfejs, np. IAutoSettingHelper
i IAutoDialHelper
.
Więcej informacji i listę funkcji interfejsu znajdziesz w sekcji Funkcje interfejsu pomocnika aplikacji na stronie 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, np. pressHome
i scroll
. Standardowa klasa pomocnicza jest zdefiniowana w pliku AbstractAutoStandardAppHelper.java
.
Framework korzysta z klas pomocniczych narzędzi. Na przykład AutoJsonUtility.java
to klasa narzędziowa, która wczytuje podany plik konfiguracji JSON urządzenia i aktualizuje konfiguracje platformy w czasie działania.
Moduł implementacji pomocnika aplikacji jest podstawą platformy Spectatio. Zawiera implementację funkcji pomocniczych zdefiniowanych w interfejsie funkcji pomocniczych aplikacji, które są wymagane do testowania aplikacji na urządzeniu samochodowym. Każda aplikacja ma własną implementację, np. SettingHelperImpl
i DialHelperImpl
, używaną przez testy motoryzacyjne do testowania aplikacji. Więcej informacji i listę implementacji znajdziesz w sekcji Funkcje implementacji narzędzia do pomocy w aplikacji w AOSP.
Testy motoryzacyjne
wykorzystują funkcje implementacji pomocnika aplikacji do testowania różnych operacji
związanych z aplikacją. Aby uzyskać dostęp do funkcji implementacji pomocnika aplikacji, użyj klasy HelperAccessor
.
Poniższy kod pokazuje 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 urządzenia, więc można ją skalować do testowania urządzeń z różnymi interfejsami i sprzętem. Aby osiągnąć taką skalowalność, Spectatio używa domyślnych konfiguracji urządzeń opartych na urządzeniu referencyjnym. Aby obsługiwać niestandardowe konfiguracje urządzeń, platforma używa w czasie działania pliku konfiguracji JSON do ustawiania żądanych zmian interfejsu na urządzeniu. Plik konfiguracji JSON obsługuje elementy interfejsu, takie jak TEXT
, DESCRIPTION
i RESOURCE_ID
, a także ustawienia path
. Musi zawierać tylko informacje o zmianach interfejsu DUT. Pozostałe elementy interfejsu korzystają z domyślnych wartości konfiguracji udostępnianych w ramach platformy.
Domyślne konfiguracje urządzeń
Poniższy przykładowy plik konfiguracji JSON zawiera dostępne konfiguracje urządzeń i ich wartości domyślne.
Kliknij tutaj, aby wyświetlić przykładowy plik konfiguracyjny JSON
{ "SETTINGS": { "APPLICATION_CONFIG": { "SETTINGS_TITLE_TEXT": "Settings", "SETTINGS_PACKAGE": "com.android.car.settings", "SETTINGS_RRO_PACKAGE": "com.android.car.settings.googlecarui.rro", "OPEN_SETTINGS_COMMAND": "am start -a android.settings.SETTINGS", "OPEN_QUICK_SETTINGS_COMMAND": "am start -n com.android.car.settings/com.android.car.settings.common.CarSettingActivity" }, "QUICK_SETTINGS": { "OPEN_MORE_SETTINGS": { "TYPE": "RESOURCE_ID", "VALUE": "toolbar_menu_item_1", "PACKAGE": "com.android.car.settings" }, "NIGHT_MODE": { "TYPE": "TEXT", "VALUE": "Night mode" } }, "DISPLAY": { "PATH": "Settings > Display", "OPTIONS": [ "Brightness level" ], "BRIGHTNESS_LEVEL": { "TYPE": "RESOURCE_ID", "VALUE": "seekbar", "PACKAGE": "com.android.car.settings" } }, "SOUND": { "PATH": "Settings > Sound", "OPTIONS": [ "Media volume", "Alarm volume" ] }, "NETWORK_AND_INTERNET": { "PATH": "Settings > Network & internet", "OPTIONS": [ ], "TOGGLE_WIFI": { "TYPE": "RESOURCE_ID", "VALUE": "master_switch", "PACKAGE": "com.android.car.settings" } }, "BLUETOOTH": { "PATH": "Settings > Bluetooth", "OPTIONS": [ ], "TOGGLE_BLUETOOTH": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_menu_item_switch", "PACKAGE": "com.android.car.settings" } }, "APPS_AND_NOTIFICATIONS": { "PATH": "Settings > Apps & notifications", "OPTIONS": [ ], "SHOW_ALL_APPS": { "TYPE": "TEXT", "VALUE": "Show all apps" }, "ENABLE_DISABLE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_menu_item_text", "PACKAGE": "com.android.car.settings" }, "DISABLE_BUTTON_TEXT": { "TYPE": "TEXT", "VALUE": "Disable" }, "ENABLE_BUTTON_TEXT": { "TYPE": "TEXT", "VALUE": "Enable" }, "DISABLE_APP_BUTTON": { "TYPE": "TEXT", "VALUE": "DISABLE APP" }, "FORCE_STOP_BUTTON": { "TYPE": "TEXT", "VALUE": "Force stop" }, "OK_BUTTON": { "TYPE": "TEXT", "VALUE": "OK" }, "PERMISSIONS_MENU": { "TYPE": "TEXT", "VALUE": "Permissions" }, "ALLOW_BUTTON": { "TYPE": "TEXT", "VALUE": "Allow" }, "DENY_BUTTON": { "TYPE": "TEXT", "VALUE": "Deny" }, "DENY_ANYWAY_BUTTON": { "TYPE": "TEXT", "VALUE": "Deny anyway" } }, "DATE_AND_TIME": { "PATH": "Settings > Date & time", "OPTIONS": [ "Automatic date & time", "Automatic time zone" ], "AUTOMATIC_DATE_AND_TIME": { "TYPE": "TEXT", "VALUE": "Automatic date & time" }, "AUTOMATIC_TIME_ZONE": { "TYPE": "TEXT", "VALUE": "Automatic time zone" }, "SET_DATE": { "TYPE": "TEXT", "VALUE": "Set date" }, "SET_TIME": { "TYPE": "TEXT", "VALUE": "Set time" }, "SELECT_TIME_ZONE": { "TYPE": "TEXT", "VALUE": "Select time zone" }, "USE_24_HOUR_FORMAT": { "TYPE": "TEXT", "VALUE": "Use 24-hour format" }, "OK_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "toolbar_menu_item_0", "PACKAGE": "com.android.car.settings" }, "NUMBER_PICKER_WIDGET": { "TYPE": "CLASS", "VALUE": "android.widget.NumberPicker" }, "EDIT_TEXT_WIDGET": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" } }, "USERS": { "PATH": "Settings > Users", "OPTIONS": [ "Guest" ] }, "ACCOUNTS": { "PATH": "Settings > Accounts", "OPTIONS": [ "Automatically sync data" ], "ADD_ACCOUNT": { "TYPE": "TEXT", "VALUE": "ADD ACCOUNT" }, "ADD_GOOGLE_ACCOUNT": { "TYPE": "TEXT", "VALUE": "Google" }, "SIGN_IN_ON_CAR_SCREEN": { "TYPE": "TEXT", "VALUE": "Sign in on car screen" }, "GOOGLE_SIGN_IN_SCREEN": { "TYPE": "TEXT", "VALUE": "Sign in to your Google Account" }, "ENTER_EMAIL": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" }, "ENTER_PASSWORD": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" }, "NEXT_BUTTON": { "TYPE": "TEXT", "VALUE": "Next" }, "DONE_BUTTON": { "TYPE": "TEXT", "VALUE": "Done" }, "REMOVE_BUTTON": { "TYPE": "TEXT", "VALUE": "Remove" }, "REMOVE_ACCOUNT_BUTTON": { "TYPE": "TEXT", "VALUE": "Remove Account" } }, "SYSTEM": { "PATH": "Settings > System", "OPTIONS": [ "About", "Legal information" ], "ABOUT_MENU": { "TYPE": "TEXT", "VALUE": "About" }, "RESET_OPTIONS_MENU": { "TYPE": "TEXT", "VALUE": "Reset options" }, "LANGUAGES_AND_INPUT_MENU": { "TYPE": "TEXT", "VALUE": "Languages & input" }, "DEVICE_MODEL": { "TYPE": "TEXT", "VALUE": "Model" }, "ANDROID_VERSION": { "TYPE": "TEXT", "VALUE": "Android version" }, "ANDROID_SECURITY_PATCH_LEVEL": { "TYPE": "TEXT", "VALUE": "Android security patch level" }, "KERNEL_VERSION": { "TYPE": "TEXT", "VALUE": "Kernel version" }, "BUILD_NUMBER": { "TYPE": "TEXT", "VALUE": "Build number" }, "RECYCLER_VIEW_WIDGET": { "TYPE": "CLASS", "VALUE": "androidx.recyclerview.widget.RecyclerView" }, "RESET_NETWORK": { "TYPE": "TEXT", "VALUE": "Reset network" }, "RESET_SETTINGS": { "TYPE": "TEXT", "VALUE": "RESET SETTINGS" }, "RESET_APP_PREFERENCES": { "TYPE": "TEXT", "VALUE": "Reset app preferences" }, "RESET_APPS": { "TYPE": "TEXT", "VALUE": "RESET APPS" }, "LANGUAGES_MENU": { "TYPE": "TEXT", "VALUE": "Languages" }, "LANGUAGES_MENU_IN_SELECTED_LANGUAGE": { "TYPE": "TEXT", "VALUE": "Idiomas" } }, "SECURITY": { "PATH": "Settings > Security", "OPTIONS": [ ], "TITLE": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_title", "PACKAGE": "com.android.car.settings.googlecarui.rro" }, "CHOOSE_LOCK_TYPE": { "TYPE": "TEXT", "VALUE": "Choose a lock type" }, "LOCK_TYPE_PASSWORD": { "TYPE": "TEXT", "VALUE": "Password" }, "LOCK_TYPE_PIN": { "TYPE": "TEXT", "VALUE": "PIN" }, "LOCK_TYPE_NONE": { "TYPE": "TEXT", "VALUE": "None" }, "CONTINUE_BUTTON": { "TYPE": "TEXT", "VALUE": "Continue" }, "CONFIRM_BUTTON": { "TYPE": "TEXT", "VALUE": "Confirm" }, "ENTER_PASSWORD": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" }, "PIN_PAD": { "TYPE": "RESOURCE_ID", "VALUE": "pin_pad", "PACKAGE": "com.android.car.settings" }, "ENTER_PIN_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "key_enter", "PACKAGE": "com.android.car.settings" }, "REMOVE_BUTTON": { "TYPE": "TEXT", "VALUE": "Remove" } } }, "PHONE": { "APPLICATION_CONFIG": { "DIAL_PACKAGE": "com.android.car.dialer", "PHONE_ACTIVITY": "com.android.car.dialer/.ui.TelecomActivity", "OPEN_DIAL_PAD_COMMAND": "am start -a android.intent.action.DIAL" }, "IN_CALL_VIEW": { "DIALED_CONTACT_TITLE": { "TYPE": "RESOURCE_ID", "VALUE": "user_profile_title", "PACKAGE": "com.android.car.dialer" }, "DIALED_CONTACT_NUMBER": { "TYPE": "RESOURCE_ID", "VALUE": "user_profile_phone_number", "PACKAGE": "com.android.car.dialer" }, "END_CALL": { "TYPE": "RESOURCE_ID", "VALUE": "end_call_button", "PACKAGE": "com.android.car.dialer" }, "MUTE_CALL": { "TYPE": "RESOURCE_ID", "VALUE": "mute_button", "PACKAGE": "com.android.car.dialer" }, "SWITCH_TO_DIAL_PAD": { "TYPE": "RESOURCE_ID", "VALUE": "toggle_dialpad_button", "PACKAGE": "com.android.car.dialer" }, "CHANGE_VOICE_CHANNEL": { "TYPE": "RESOURCE_ID", "VALUE": "voice_channel_view", "PACKAGE": "com.android.car.dialer" }, "VOICE_CHANNEL_CAR": { "TYPE": "TEXT", "VALUE": "Car speakers" }, "VOICE_CHANNEL_PHONE": { "TYPE": "TEXT", "VALUE": "Phone" } }, "DIAL_PAD_VIEW": { "DIAL_PAD_MENU": { "TYPE": "TEXT", "VALUE": "Dial Pad" }, "DIAL_PAD_FRAGMENT": { "TYPE": "RESOURCE_ID", "VALUE": "dialpad_fragment", "PACKAGE": "com.android.car.dialer" }, "DIALED_NUMBER": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.dialer" }, "MAKE_CALL": { "TYPE": "RESOURCE_ID", "VALUE": "call_button", "PACKAGE": "com.android.car.dialer" }, "DELETE_NUMBER": { "TYPE": "RESOURCE_ID", "VALUE": "delete_button", "PACKAGE": "com.android.car.dialer" } }, "CONTACTS_VIEW": { "CONTACTS_MENU": { "TYPE": "TEXT", "VALUE": "Contacts" }, "CONTACT_INFO": { "TYPE": "RESOURCE_ID", "VALUE": "call_action_id", "PACKAGE": "com.android.car.dialer" }, "CONTACT_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.dialer" }, "CONTACT_DETAIL": { "TYPE": "RESOURCE_ID", "VALUE": "show_contact_detail_id", "PACKAGE": "com.android.car.dialer" }, "ADD_CONTACT_TO_FAVORITE": { "TYPE": "RESOURCE_ID", "VALUE": "contact_details_favorite_button", "PACKAGE": "com.android.car.dialer" }, "SEARCH_CONTACT": { "TYPE": "RESOURCE_ID", "VALUE": "menu_item_search", "PACKAGE": "com.android.car.dialer" }, "CONTACT_SEARCH_BAR": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_search_bar", "PACKAGE": "com.android.car.dialer" }, "SEARCH_RESULT": { "TYPE": "RESOURCE_ID", "VALUE": "contact_name", "PACKAGE": "com.android.car.dialer" }, "CONTACT_SETTINGS": { "TYPE": "RESOURCE_ID", "VALUE": "menu_item_setting", "PACKAGE": "com.android.car.dialer" }, "CONTACT_ORDER": { "TYPE": "TEXT", "VALUE": "Contact order" }, "SORT_BY_FIRST_NAME": { "TYPE": "TEXT", "VALUE": "First name" }, "SORT_BY_LAST_NAME": { "TYPE": "TEXT", "VALUE": "Last Name" }, "CONTACT_TYPE_WORK": { "TYPE": "TEXT", "VALUE": "Work" }, "CONTACT_TYPE_MOBILE": { "TYPE": "TEXT", "VALUE": "Mobile" }, "CONTACT_TYPE_HOME": { "TYPE": "TEXT", "VALUE": "Home" } }, "CALL_HISTORY_VIEW": { "CALL_HISTORY_MENU": { "TYPE": "TEXT", "VALUE": "Recents" }, "CALL_HISTORY_INFO": { "TYPE": "RESOURCE_ID", "VALUE": "call_action_id", "PACKAGE": "com.android.car.dialer" } }, "FAVORITES_VIEW": { "FAVORITES_MENU": { "TYPE": "TEXT", "VALUE": "Favorites" } } }, "NOTIFICATIONS": { "APPLICATION_CONFIG": { "OPEN_NOTIFICATIONS_COMMAND": "service call statusbar 1" }, "EXPANDED_NOTIFICATIONS_SCREEN": { "NOTIFICATION_VIEW": { "TYPE": "RESOURCE_ID", "VALUE": "notification_view", "PACKAGE": "com.android.systemui" }, "CLEAR_ALL_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "clear_all_button", "PACKAGE": "com.android.systemui" }, "STATUS_BAR": { "TYPE": "RESOURCE_ID", "VALUE": "car_top_navigation_bar_container", "PACKAGE": "com.android.systemui" }, "APP_ICON": { "TYPE": "RESOURCE_ID", "VALUE": "app_icon", "PACKAGE": "com.android.systemui" }, "APP_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "header_text", "PACKAGE": "com.android.systemui" }, "NOTIFICATION_TITLE": { "TYPE": "RESOURCE_ID", "VALUE": "notification_body_title", "PACKAGE": "com.android.systemui" }, "NOTIFICATION_BODY": { "TYPE": "RESOURCE_ID", "VALUE": "notification_body_content", "PACKAGE": "com.android.systemui" }, "CARD_VIEW": { "TYPE": "RESOURCE_ID", "VALUE": "card_view", "PACKAGE": "com.android.systemui" } } }, "MEDIA_CENTER": { "APPLICATION_CONFIG": { "MEDIA_CENTER_PACKAGE": "com.android.car.media", "MEDIA_ACTIVITY": "com.android.bluetooth/com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService" }, "MEDIA_CENTER_SCREEN": { "PLAY_PAUSE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "play_pause_stop", "PACKAGE": "com.android.car.media" }, "NEXT_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_next", "PACKAGE": "com.android.car.media" }, "PREVIOUS_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_prev", "PACKAGE": "com.android.car.media" }, "SHUFFLE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "overflow_on", "PACKAGE": "com.android.car.media" }, "PLAY_QUEUE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "play_queue", "PACKAGE": "com.android.car.media" }, "MINIMIZED_MEDIA_CONTROLS": { "TYPE": "RESOURCE_ID", "VALUE": "minimized_playback_controls", "PACKAGE": "com.android.car.media" }, "TRACK_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.media" }, "TRACK_NAME_MINIMIZED_CONTROL": { "TYPE": "RESOURCE_ID", "VALUE": "minimized_control_bar_title", "PACKAGE": "com.android.car.media" }, "BACK_BUTTON": { "TYPE": "DESCRIPTION", "VALUE": "Back" } }, "MEDIA_CENTER_ON_HOME_SCREEN": { "PLAY_PAUSE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "play_pause_stop", "PACKAGE": "com.android.car.carlauncher" }, "NEXT_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_next", "PACKAGE": "com.android.car.carlauncher" }, "PREVIOUS_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_prev", "PACKAGE": "com.android.car.carlauncher" }, "TRACK_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.carlauncher" } } } }
Konfiguracje urządzeń alternatywnych
Poniższy przykładowy kod pokazuje plik konfiguracyjny JSON, w którym ustawienia domyślne są zastępowane przez ustawienia na urządzeniu. W tym przykładzie:
Ustawienia internetu na urządzeniach referencyjnych noszą nazwę Sieć i internet, a na urządzeniu DUT – Łączność.
Ustawienia daty i godziny są dostępne w przypadku urządzeń referencyjnych w sekcji Ustawienia > Data i godzina, a w przypadku testowanego urządzenia – w sekcji Ustawienia > System > Data i godzina.
// Default configuration file
{
....
"SECURITY_SETTINGS_SCROLL_ELEMENT": {
"TYPE": "RESOURCE_ID",
"VALUE": "fragment_container",
},
....
}
// JSON configuration file for non-reference device
{
....
"SECURITY_SETTINGS_SCROLL_ELEMENT": {
"TYPE": "RESOURCE_ID",
"VALUE": "car_ui_recycler_view"
},
....
}
Gdy plik konfiguracyjny JSON jest gotowy, jest on udostępniany w czasie działania, 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 testowanego urządzenia. 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
Konfiguracja zawiera 5 obiektów najwyższego poziomu o tych kluczach i wartościach:
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 wskazujący typy działań i parametry różnych działań. Możesz na przykład wybrać, czy do przewijania chcesz używać przycisków czy gestu. |
COMMANDS |
Obiekt określający polecenia, które wykonują różne działania. |
UI_ELEMENTS |
Obiekt służący do tworzenia selektorów UI Automator `BySelectors`, które wybierają elementy interfejsu (opisane szczegółowo poniżej). |
WORKFLOWS |
Sekwencje działań, które wykonują zadania wyższego poziomu (opisane szczegółowo poniżej). |
Elementy interfejsu
Każdy element interfejsu ma TYPE
, który określa, 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 zidentyfikuje element na ekranie za pomocą tej konfiguracji, otrzyma dokładnie jeden element. Jeśli do konfiguracji pasuje wiele elementów, w teście zostanie użyty dowolny z nich. Dlatego konfiguracja powinna być (zwykle) wystarczająco szczegółowa, aby w odpowiednim kontekście ograniczać się do jednego elementu.
TEKST
To najprostszy typ elementu interfejsu. Element interfejsu jest identyfikowany na podstawie tekstu i wymaga dopasowania ścisłego.
"CALL_HISTORY_MENU": {
"TYPE": "TEXT",
"VALUE": "Recents"
}
TEXT_CONTAINS
Podobnie jak TEXT
, z tym wyjątkiem, że określony VALUE
musi pojawić się tylko w tekście elementu, aby został dopasowany.
"PRIVACY_CALENDAR": {
"TYPE": "TEXT_CONTAINS",
"VALUE": "Calendar"
}
OPIS
Wyszukaj element na podstawie atrybutu opisu treści, wymagając dokładnego dopasowania.
"APP_GRID_SCROLL_BACKWARD_BUTTON": {
"TYPE": "DESCRIPTION",
"VALUE": "Scroll up"
}
RESOURCE_ID
Zidentyfikuj element na podstawie jego identyfikatora zasobu, opcjonalnie sprawdzając też komponent pakietu tego identyfikatora. Klucz PACKAGE
jest opcjonalny. Jeśli go pominiesz, będzie pasować do dowolnego pakietu, a pod uwagę będzie brana tylko część identyfikatora po znaku :id/
.
"APP_LIST_SCROLL_ELEMENT": {
"TYPE": "RESOURCE_ID",
"VALUE": "apps_grid",
"PACKAGE": "com.android.car.carlauncher"
}
KLIKALNE, MOŻLIWE DO PRZEWIJANIA
Określ element na podstawie tego, czy można go kliknąć lub przewinąć.
Są to bardzo ogólne typy elementów, które zwykle powinny być używane tylko w MULTIPLE
, aby zawęzić inny typ elementu. Klucz FLAG
jest opcjonalny i domyślnie ma wartość true
.
"SAMPLE_ELEMENT": {
"TYPE": "CLICKABLE",
"FLAG": false
}
KLASA
Określ element na podstawie jego klasy.
"SECURITY_SETTINGS_ENTER_PASSWORD": {
"TYPE": "CLASS",
"VALUE": "android.widget.EditText"
}
HAS_ANCESTOR
Zidentyfikuj element, sprawdzając hierarchię widżetów u jego przodków. Klucz ANCESTOR
zawiera obiekt, który identyfikuje element nadrzędny. Klucz DEPTH
określa, jak daleko w górę hierarchii ma sięgać wyszukiwanie. DEPTH
jest opcjonalny i ma domyślną wartość 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_ANCESTOR",
"DEPTH": 2,
"ANCESTOR": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
HAS_DESCENDANT
Zidentyfikuj element, przeglądając hierarchię jego elementów podrzędnych. Klucz DESCENDANT
zawiera obiekt, który określa element podrzędny do wyszukania. Klucz DEPTH
określa, jak daleko w górę hierarchii ma sięgać wyszukiwanie. DEPTH
jest opcjonalne i ma domyślną wartość 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_DESCENDANT",
"DEPTH": 2,
"DESCENDANT": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
WIELOKROTNE
Określ element na podstawie wielu warunków, które muszą być spełnione jednocześnie.
"APP_INFO_SETTINGS_PERMISSION_MANAGER": {
"TYPE": "MULTIPLE",
"SPECIFIERS": [
{
"TYPE": "CLASS",
"VALUE": "android.widget.RelativeLayout"
},
{
"TYPE": "HAS_DESCENDANT",
"MAX_DEPTH": 2,
"DESCENDANT": {
"TYPE": "TEXT",
"VALUE": "Permission manager"
}
}
]
}
W tym przykładzie konfiguracja identyfikuje element RelativeLayout
, który ma element podrzędny na poziomie 2
, zawierający tekst Permission manager
.
Workflows
Przepływ pracy to sekwencja działań służących do wykonania określonego zadania, która może się różnić w zależności od typu urządzenia i jest bardziej elastyczna 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ść, w której klucz jest nazwą przepływu pracy, a wartość to tablica działań do wykonania. Każda czynność ma NAME
, TYPE
, (zwykle) CONFIG
oraz (czasami) SWIPE_CONFIG
lub SCROLL_CONFIG
. W przypadku większości TYPÓW CONFIG
to obiekt z kluczem UI_ELEMENT
, którego wartość ma taką samą postać jak wpis elementu interfejsu (patrz wyżej). Są to:
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 pozostałych TYPÓW szczegóły konfiguracji są następujące:
Obiekt | Opis |
---|---|
COMMAND |
Obiekt z wartością TEXT zawierającą polecenie do wykonania. |
HAS_PACKAGE_IN_FOREGROUND |
Obiekt z wartością TEXT zawierającą pakiet. |
SWIPE |
W przypadku działania SWIPE pomiń znak CONFIG key . Ta funkcja korzysta tylko z SWIPE_CONFIG |
WAIT_MS |
Obiekt z wartością TEXT zawierającą liczbę milisekund, które należy odczekać. |
Działania 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 do przewijania, w takiej samej formie jak konfiguracja elementu interfejsu (patrz wyżej). |
SCROLL_FORWARD , SCROLL_BACKWARD |
przyciski przewijania do przodu i do tyłu (wymagane, gdy SCROLL_ACTION ma wartość USE_BUTTON ); |
SCROLL_MARGIN |
Jeśli SCROLL_ACTION ma wartość USE_GESTURE , odległość od krawędzi kontenera, w której należy rozpocząć i zakończyć przeciąganie, aby przewinąć zawartość (opcjonalnie, domyślnie 10). |
SCROLL_WAIT_TIME |
Jeśli wartość SCROLL_ACTION to USE_GESTURE , jest to czas w milisekundach, jaki należy odczekać między gestami przewijania podczas wyszukiwania obiektu, który ma zostać kliknięty.
(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 |
Jedna z tych opcji:
|
NUMBER_OF_STEPS |
Liczba kroków, które należy wykonać, aby przesunąć palcem. Zobacz
segmentSteps .
|
Tworzenie i wykonywanie
Platforma Spectatio jest automatycznie tworzona w ramach testowego pliku APK. Aby utworzyć testowy plik APK, kod źródłowy AOSP musi znajdować się na lokalnej stacji roboczej. Po utworzeniu testowego pliku APK użytkownik musi zainstalować go na urządzeniu i przeprowadzić test.
Poniższy przykładowy kod pokazuje tworzenie, instalowanie i wykonywanie 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 wartość TEST-APK-NAME na
AndroidAutomotiveSettingsTests
, aby przetestować ustawienia Wi-Fi zgodnie z plikiemAndroid.bp
. Nazwę pliku APK znajdziesz w odpowiednim plikuAndroid.bp
w przypadku testu aplikacji samochodowej.DEVICE-SERIAL: numer seryjny testowanego urządzenia. Ten parametr nie jest wymagany, jeśli z hostem połączone jest tylko jedno urządzenie.
config-file-path
: parametr opcjonalny, który jest wymagany tylko w przypadku udostępniania niestandardowych konfiguracji interfejsu urządzenia zgodnie z opisem w pliku konfiguracji JSON. Jeśli nie podasz tych wartości, platforma użyje wartości domyślnych do przeprowadzenia testów.PATH-FOR-BUILT-TEST-APK: ścieżka, w której tworzony jest testowy plik APK po wykonaniu polecenia
make
.TEST-PACKAGE: nazwa pakietu testowego.
TEST-CLASSNAME: nazwa klasy testu. Na przykład w przypadku testu Ustawienia Wi-Fi pakiet testowy to
android.platform.tests
, a nazwa klasy testowej toWifiSettingTest
.
Biblioteka fragmentów dotyczących motoryzacji
Biblioteka fragmentów kodu Automotive to zestaw bibliotek testowych Androida dla Projektu Android Open Source Project (AOSP), które umożliwiają interakcję z aplikacjami i usługami motoryzacyjnymi. Wykorzystuje Spectatio z wygodnym mechanizmem wykonywania zdalnych wywołań procedur (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 niezbędnymi 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 w bibliotece fragmentów kodu dla branży motoryzacyjnej, możesz użyć podanego pliku android.bp
. Aby skompilować plik APK, użyj poleceń z poprzedniej sekcji.
Wdrażanie
Po pomyślnym skompilowaniu bibliotek fragmentów wdróż uzyskane pliki APK na urządzeniu docelowym za pomocą polecenia adb install
wspomnianego 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ływać za pomocą platformy Mobly z komputera hosta. Jeśli 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ć na urządzeniu metody RPC. Przykładowe wywołanie:
python3 snippet_shell.py com.google.android.mobly.snippet.bundled -s <serial>
Zastąp <serial>
numerem seryjnym urządzenia, który możesz uzyskać za pomocą polecenia adb devices, jeśli podłączonych jest wiele urządzeń.
Uwzględnione biblioteki
Biblioteka fragmentów kodu dla branży motoryzacyjnej zawiera te biblioteki fragmentów kodu i funkcje pomocnicze:
AutomotiveSnippet: udostępnia interfejsy API związane z obsługą pojazdu, takie jak wybieranie numeru, sterowanie głośnością, klawisze fizyczne pojazdu i interakcja z centrum multimediów.
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ę.
Możesz w szczególności naruszać wywołania RCP związane z Bluetooth, aby sparować urządzenie samochodowe z telefonem. Ten bt_discovery_test
pokazuje, jak to zrobić.
- TEST-CLASSNAME: nazwa klasy testu. Na przykład w przypadku testu Ustawienia Wi-Fi pakiet testowy to
android.platform.tests
, a nazwa klasy testowej toWifiSettingTest
.