Spectatio: система автомобильных испытаний

Spectatio — это платформа тестирования с открытым исходным кодом, разработанная для тестирования Android Automotive OS (AAOS) на реальных и виртуальных устройствах. Spectatio предоставляет API для тестирования приложений на автомобильном устройстве и представляет собой расширяемое и масштабируемое решение, используемое для проверки возможностей и производительности AAOS и его приложений.

Дизайн высокого уровня

Платформа Spectatio адаптируется и расширяется для различных реализаций пользовательского интерфейса AAOS. Он используется для тестирования возможностей и производительности AAOS на аппаратном обеспечении устройств, эмуляторах и виртуализированных средах.

На следующем рисунке поясняется высокоуровневый дизайн платформы Spectatio.

Высокоуровневый дизайн Spectatio Framework

Рисунок 1. Высокоуровневый проект платформы Spectatio.

Платформа Spectatio, построенная на основе UI Automator , предоставляет набор API для создания тестов пользовательского интерфейса, которые взаимодействуют с пользовательскими и системными приложениями в AAOS. В автомобильных тестах используются API-интерфейсы, предоставляемые платформой Spectatio для тестирования, что делает эти тесты независимыми от тестируемого устройства (DUT) и масштабируемыми для тестирования различных устройств, если они поддерживаются.

На рисунке 1 показано, что платформа Spectatio имеет модульную структуру на основе эталонных приложений, таких как Dialer, Medicenter и Settings, с использованием интерфейсов и помощников для конкретных приложений, что позволяет легко расширять ее для новых приложений. Платформа Spectatio повторно использует общие стандартные и служебные вспомогательные классы. Стандартный вспомогательный класс является родительским классом для всех вспомогательных функций приложения и предоставляет стандартные функции, которые зависят от устройства или применимы ко всем приложениям. Вспомогательные классы утилит предоставляют такие утилиты, как чтение или запись файлов с устройства.

Архитектура

Чтобы предоставить набор API для создания тестов пользовательского интерфейса, платформа Spectatio реализует интерфейсы и помощники для конкретных приложений, одновременно расширяя существующий стандартный вспомогательный класс и импортируя служебные вспомогательные классы.

На рис. 2 показана высокоуровневая архитектура платформы Spectatio и все объекты, участвующие в реализации API для тестирования приложения.

Высокоуровневая архитектура Spectatio Framework

Рисунок 2. Архитектура высокого уровня платформы Spectatio.

Интерфейс помощника приложения предоставляет схему реализации помощника приложения. Он состоит из различных вспомогательных функций, необходимых для тестирования приложений. Каждое приложение имеет собственный интерфейс, например IAutoSettingHelper и IAutoDialHelper . Дополнительную информацию и список функций интерфейса см. в разделе Функции интерфейса помощника приложения на AOSP.

Стандартный вспомогательный класс состоит из стандартных атрибутов и функций, которые необходимы для настройки устройства, но не относятся к какому-либо приложению, например pressHome и scroll . Стандартный вспомогательный класс определен в AbstractAutoStandardAppHelper.java .

Вспомогательные классы утилиты используются платформой. Например, AutoJsonUtility.java — это служебный класс, который загружает заданный файл конфигурации JSON устройства и обновляет конфигурации платформы во время выполнения.

Модуль реализации помощника приложения является ядром платформы Spectatio. Он содержит реализацию вспомогательных функций, определенных в вспомогательном интерфейсе приложения, которые необходимы для тестирования приложений на автомобильном устройстве. Каждое приложение имеет собственную реализацию, например SettingHelperImpl и DialHelperImpl , используемые автомобильными тестами для тестирования приложений. Дополнительную информацию и список реализаций см. в разделе «Функции реализации помощника приложения » на AOSP.

Автомобильные тесты используют вспомогательные функции реализации приложения для тестирования различных операций, связанных с приложением. Используйте класс HelperAccessor , чтобы получить доступ к функциям реализации вспомогательного приложения.

Следующий код показывает настройку, очистку и выполнение примера автомобильного теста.

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

Кастомизация

Платформа Spectatio не зависит от пользовательского интерфейса устройства, поэтому ее можно масштабировать для тестирования устройств с различными пользовательскими интерфейсами и оборудованием. Для достижения такой масштабируемости Spectatio использует конфигурации устройств по умолчанию на основе эталонного устройства. Для поддержки конфигураций устройств, отличных от настроек по умолчанию, платформа использует файл конфигурации JSON во время выполнения, чтобы задать желаемые изменения пользовательского интерфейса для устройства. Файл конфигурации JSON поддерживает такие элементы пользовательского интерфейса, как TEXT , DESCRIPTION и RESOURCE_ID , а также настройки path и должен содержать только информацию об изменениях пользовательского интерфейса для тестируемого устройства. Остальные элементы пользовательского интерфейса используют значения конфигурации по умолчанию, предусмотренные в платформе.

Конфигурации устройств по умолчанию

В следующем примере файла конфигурации JSON показаны доступные конфигурации устройств и их значения по умолчанию.

Нажмите здесь, чтобы отобразить образец файла конфигурации 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"
                        }
                }
        }
}
  

Альтернативные конфигурации устройства

В следующем примере кода показан пример файла конфигурации JSON, в котором настройки по умолчанию переопределяются настройками тестируемого устройства. В этом примере:

  • Настройки Интернета называются «Сеть и Интернет» на эталонных устройствах и «Подключение» на тестируемом устройстве.

  • Настройки даты и времени доступны в разделе «Настройки» > «Дата и время» для эталонных устройств и в «Настройки» > «Система» > «Дата и время» для тестируемого устройства.

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

Когда файл конфигурации JSON готов, он предоставляется во время выполнения, как показано в следующем блоке кода:

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

В этой команде:

  • DEVICE-SERIAL : Серийный идентификатор тестируемого устройства. Этот параметр не требуется, если к хосту подключено только одно устройство.

  • PATH-TO-JSON-FILE : путь к файлу JSON на хост-компьютере.

Формат конфигурации

В конфигурации имеется пять объектов верхнего уровня со следующими ключами и значениями:

Объект Описание
PACKAGES Объект, описывающий основной пакет для различных приложений, который используется для определения того, когда это приложение находится на переднем плане.
ACTIONS Объект, указывающий типы действий и параметры для различных действий. Например, использовать ли кнопки или жест для прокрутки.
COMMANDS Объект, определяющий команды, выполняющие различные действия.
UI_ELEMENTS Объект, используемый для создания UI Automator BySelectors, который выбирает элементы пользовательского интерфейса (подробно описано ниже).
WORKFLOWS Последовательность действий, выполняющих задачи высокого уровня (подробно описанные ниже).

элементы пользовательского интерфейса

Каждый элемент пользовательского интерфейса имеет TYPE , который определяет, что UI Automator будет искать для идентификации элемента (например, идентификатор ресурса, текст и описание) и значений конфигурации, связанных с этим типом. В общем, всякий раз, когда помощник идентифицирует элемент на экране, используя эту конфигурацию, он получает ровно один элемент. Если конфигурации соответствуют несколько элементов, в тесте используется произвольный. Следовательно, конфигурация должна (как правило) быть написана достаточно конкретно, чтобы она сводилась к одному элементу в соответствующем контексте.

ТЕКСТ

Это самый простой тип элемента пользовательского интерфейса. Элемент пользовательского интерфейса идентифицируется по тексту и требует точного совпадения.

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

ТЕКСТ_CONTAINS

То же, что и TEXT , за исключением того, что указанное VALUE должно появиться только где-то в тексте сопоставляемого элемента.

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

ОПИСАНИЕ

Идентифицируйте элемент по его атрибуту описания содержимого, требующему точного совпадения.

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

RESOURCE_ID

Определите элемент по его идентификатору ресурса, при необходимости также проверив компонент пакета с этим идентификатором. Ключ PACKAGE не является обязательным; если этот параметр опущен, будет соответствовать любой пакет, и будет учитываться только часть идентификатора, следующая за :id/ .

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

КЛИКАЕМЫЕ, ПРОКРУТЛЯЕМЫЕ

Определите элемент по тому, доступен ли он (или нет) для кликов или прокрутки. Это очень общие типы элементов, и их обычно следует использовать только в составе MULTIPLE чтобы сузить другой тип элемента. Ключ FLAG является необязательным и по умолчанию имеет значение true .

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

СОРТ

Определите элемент по его классу.

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

HAS_ANCESTOR

Идентифицируйте элемент, просматривая иерархию виджетов по его предкам. Ключ ANCESTOR содержит объект, идентифицирующий предка. Ключ DEPTH определяет, насколько высоко следует просматривать иерархию. DEPTH не является обязательным и имеет значение по умолчанию 1 .

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

HAS_DESCENDANT

Определите элемент, просмотрев иерархию его дочерних элементов. Ключ DESCENDANT содержит объект, определяющий искомого дочернего элемента. Ключ DEPTH определяет, насколько высоко следует просматривать иерархию. DEPTH не является обязательным и имеет значение по умолчанию 1 .

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

НЕСКОЛЬКО

Определите элемент на основе нескольких одновременных условий, все из которых должны быть соблюдены.

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

В этом примере конфигурация определяет RelativeLayout , имеющий потомка на глубине 2 , который имеет текстовый Permission manager .

Рабочие процессы

Рабочий процесс представляет собой последовательность действий, используемых для выполнения конкретной задачи, которая может существенно различаться в зависимости от типа устройства и которую более гибко представить в конфигурации, чем в коде.

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

Каждый рабочий процесс представляет собой пару «ключ-значение», где ключ — это имя рабочего процесса, а значение — массив действий, которые необходимо выполнить. Каждое действие имеет NAME , TYPE , (обычно) CONFIG и (иногда) SWIPE_CONFIG или SCROLL_CONFIG . Для большинства TYPE CONFIG — это объект с ключом UI_ELEMENT , значение которого принимает ту же форму, что и запись элемента пользовательского интерфейса (см. выше). Эти ТИПЫ:

НАЖИМАТЬ
LONG_PRESS
НАЖМИТЕ
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

Для других ТИПА сведения о конфигурации следующие:

Объект Описание
COMMAND Объект со значением TEXT содержащий команду для выполнения.
HAS_PACKAGE_IN_FOREGROUND Объект со значением TEXT содержащий пакет.
SWIPE Опустите CONFIG key для действия SWIPE . При этом используется только SWIPE_CONFIG
WAIT_MS Объект со значением TEXT содержащим количество миллисекунд ожидания.

Действия, связанные с прокруткой и пролистыванием, требуют дополнительной настройки, а именно:

СКРОЛЛ_КОНФИГ

Объект Описание
SCROLL_ACTION Либо USE_GESTURE , либо USE_BUTTON
SCROLL_DIRECTION Либо HORIZONTAL , либо VERTICAL
SCROLL_ELEMENT Объект, указывающий контейнер для прокрутки, использующий ту же форму, что и конфигурация элемента пользовательского интерфейса (см. выше).
SCROLL_FORWARD , SCROLL_BACKWARD Кнопки прокрутки вперед и назад (обязательны, если SCROLL_ACTION имеет значение USE_BUTTON ).
SCROLL_MARGIN Если SCROLL_ACTION имеет значение USE_GESTURE , это расстояние от края контейнера для начала и остановки перетаскивания, которое будет использоваться для выполнения прокрутки ( необязательно, по умолчанию = 10).
SCROLL_WAIT_TIME Если SCROLL_ACTION имеет USE_GESTURE , время ожидания в миллисекундах между жестами прокрутки при поиске объекта для щелчка. ( Необязательно, по умолчанию = 1).

SWIPE_CONFIG

Объект Описание
SWIPE_DIRECTION Либо TOP_TO_BOTTOM , BOTTOM_TO_TOP , LEFT_TO_RIGHT или RIGHT_TO_LEFT
SWIPE_FRACTION

Одно из следующих:

  • FULL : жест пролистывания от края экрана к краю экрана.

    ИЛИ,
  • DEFAULT : От края до края экрана, с буфером в пять (5) пикселей с каждой стороны.

    ИЛИ,
  • THREE_QUARTER , HALF или QUARTER : жест пролистывания заканчивается в пяти (5) пикселях от края экрана и начинается в такой точке, которая охватывает указанное расстояние экрана.
NUMBER_OF_STEPS Количество шагов, которые необходимо использовать для выполнения пролистывания. См. раздел segmentSteps .

Стройте и выполняйте

Платформа Spectatio автоматически создается как часть тестового APK. Для сборки тестового APK база кода AOSP должна находиться на локальной рабочей станции. После создания тестового APK пользователь должен установить APK на устройство и выполнить тест.

В следующем примере кода показано создание, установка и выполнение тестового 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

В этих командах:

  • TEST-APK-NAME : имя тестируемого приложения. Например, задайте для TEST-APK-NAME значение AndroidAutomotiveSettingsTests , чтобы проверить настройки Wi-Fi, указанные в файле Android.bp . Название APK можно найти в соответствующем файле Android.bp для автомобильного теста .

  • DEVICE-SERIAL : серийный идентификатор тестируемого устройства. Этот параметр не требуется, если к хосту подключено только одно устройство.

  • config-file-path : необязательный параметр, который необходим только для предоставления конфигураций пользовательского интерфейса устройства, отличных от стандартных, как указано в файле конфигурации JSON . Если этот параметр не указан, платформа использует значения по умолчанию для выполнения тестов.

  • PATH-FOR-BUILT-TEST-APK : путь, по которому создается тестовый APK при выполнении команды make .

  • TEST-PACKAGE : Имя тестового пакета.

  • TEST-CLASSNAME : Имя тестового класса. Например, для теста настроек Wi-Fi тестовый пакет — android.platform.tests , а имя тестового класса — WifiSettingTest .

Библиотека автомобильных фрагментов

Библиотека автомобильных фрагментов — это набор тестовых библиотек Android для проекта Android с открытым исходным кодом (AOSP), предназначенных для взаимодействия с автомобильными приложениями и службами. Он использует Spectatio с удобным механизмом выполнения удаленных вызовов процедур (RPC) с хост-машины (тестовой) на устройство под управлением Android.

Начать

Прежде чем начать, просмотрите эти разделы.

Предварительные условия

  • Python 3.x установлен на хост-компьютере.
  • Настройка среды AOSP с необходимыми инструментами сборки.
  • Автомобильное устройство Android (эмулятор или физическое устройство) с доступом к adb.

Сборник

Чтобы скомпилировать различные фрагменты, предоставленные Библиотекой автомобильных фрагментов, вы можете использовать предоставленный файл android.bp . Следующие команды из предыдущего раздела для компиляции APK.

Развертывание

После успешной компиляции библиотек фрагментов разверните полученные APK-файлы на целевом устройстве с помощью команды adb install упомянутой в предыдущем разделе.

Запуск тестов

Библиотеки фрагментов предоставляют несколько методов RPC для взаимодействия с автомобильной системой. Эти методы можно вызывать через платформу Mobly с хост-компьютера. Предполагая, что у вас настроена тестовая среда Mobly, вы можете использовать сценарий snippet_shell.py , чтобы открыть интерактивную оболочку Python, где вы можете вручную вызывать методы RPC на устройстве. Пример вызова:

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

Замените <serial> серийным номером устройства, который вы можете получить с помощью устройств adb, если подключено несколько устройств.

Включенные библиотеки

Библиотека автомобильных фрагментов включает в себя следующие библиотеки и помощники фрагментов:

  • AutomotiveSnippet: предоставляет API-интерфейсы, связанные с операциями автомобиля, такими как набор номера, регулировка громкости, аппаратные клавиши автомобиля и взаимодействие с медиацентром.

  • PhoneSnippet: предоставляет API-интерфейсы, связанные с телефонией, включая обработку вызовов, просмотр контактов и операции с SMS.

Фрагмент Automotive и PhoneSnippet имеют общую логику. В частности, вы можете вторгаться в вызовы RCP, связанные с Bluetooth, для сопряжения автомобиля и телефонного устройства. Этот bt_discovery_test показывает, как это сделать.