Spectatio:Automotive 测试框架

Spectatio 是一个开源测试框架,用于在真实设备和虚拟设备上测试 Android Automotive OS (AAOS)。Spectatio 提供用于在汽车设备上测试应用的 API,它是一种可扩展、可伸缩的解决方案,用于验证 AAOS 及其应用的功能和性能。

概要设计

Spectatio 框架可适应各种 AAOS 界面实现,并相应地扩展。该框架用于在设备硬件、模拟器和虚拟环境中测试 AAOS 的功能和性能。

下图说明了 Spectatio 框架的概要设计。

Spectatio 框架概要设计

图 1. Spectatio 框架概要设计

Spectatio 框架基于 UI Automator 构建,该框架提供了一组 API,这些 API 可用于构建与 AAOS 用户和系统应用交互的界面测试。Automotive 测试使用 Spectatio 框架提供的 API 进行测试,所以这些测试独立于受测设备 (DUT),并且可扩展为测试各种设备(如果支持)。

图 1 显示 Spectatio 框架基于拨号器、Medicenter 和“设置”等参考应用实现了模块化,并使用应用专用的接口和辅助程序,使其能够针对新应用轻松扩展。Spectatio 框架会重复利用通用标准和实用程序辅助类。标准辅助类是所有应用辅助函数的父类,它提供设备专用或适用于各种应用的标准函数。实用程序辅助类提供了各种实用程序,例如从设备读取或写入文件的实用程序。

架构

为了提供一组 API 来构建界面测试,Spectatio 框架实现了应用专用的界面和辅助程序,同时扩展现有的标准辅助类,并导入实用程序辅助类。

图 2 展示了 Spectatio 框架的概要架构,以及为应用测试实现 API 时所涉及的所有实体。

Spectatio 框架概要架构

图 2. Spectatio 框架的概要架构。

应用辅助接口提供了实现应用辅助程序的蓝图。它包含测试应用所需的各种辅助函数。每个应用都有自己的接口,例如 IAutoSettingHelperIAutoDialHelper。如需了解详情及查看接口函数列表,请参阅 AOSP 上的应用辅助接口函数

标准辅助类包含设备设置所需的标准属性和函数(但不特定于任何应用,例如 pressHomescroll)。标准辅助类需在 AbstractAutoStandardAppHelper.java 中定义。

Spectatio 框架会使用实用工具辅助类。例如,AutoJsonUtility.java 是一个实用程序类,用于加载给定的设备 JSON 配置文件并在运行时更新框架配置。

应用辅助程序实现模块是 Spectatio 框架的核心。该模块包含应用辅助接口中所定义辅助函数的实现,而相应辅助函数是在汽车设备上测试应用所必需的函数。每个应用都有自己的实现(如 SettingHelperImplDialHelperImpl),Automotive 测试会利用这些实现来测试应用。如需了解详情和实现列表,请参阅 AOSP 上的应用辅助程序实现函数

Automotive 测试使用应用辅助程序实现函数来测试与应用相关的各种操作。使用 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 配置文件支持 TEXTDESCRIPTIONRESOURCE_ID 等界面元素以及 path 设置,并且只能包含有关 DUT 的界面更改的信息。其余界面元素会使用该框架中提供的默认配置值。

默认设备配置

下方的 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 配置文件的示例,其中默认设置已由 DUT 上的设置替换。在此示例中:

  • 网络设置在参考设备上被命名为网络和互联网,在 DUT 上被命名为网络连接

  • 对于参考设备,可在设置 > 日期和时间下找到日期和时间设置;对于 DUT,可在设置 > 系统 > 日期和时间下找到日期和时间设置。

// 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:DUT 的序列号。如果只有 1 部设备连接到宿主机,则无需使用此参数。

  • PATH-TO-JSON-FILE:宿主机上的 JSON 文件路径。

配置格式

配置中有五个顶级对象,它们各有以下键和值:

对象 说明
PACKAGES 用于描述各种应用的主要软件包的对象,用于确定相应应用何时处于前台。
ACTIONS 一个对象,用于指明各种操作的操作类型和参数。例如,是使用按钮还是使用手势来滚动。
COMMANDS 一个对象,用于指定执行各种操作的命令。
UI_ELEMENTS 一个对象,用于构建会选择界面元素的界面自动化程序“BySelectors”(详见下文)。
WORKFLOWS 一个操作序列,用于完成高级任务(详见下文)。

界面元素

每个界面元素都有一个 TYPE,以指定 UI Automator 将查找的元素识别信息(例如资源 ID、文本和说明),以及与该类型关联的配置值。一般来说,每当辅助程序使用此配置识别屏幕上的元素时,它都会获得恰好 1 个元素。如果有多个元素与配置匹配,则在测试中使用任意元素。因此,配置(通常)应该足够具体,以便在相关上下文中缩小到一个元素。

TEXT

这是最简单的界面元素类型。界面元素由其文本标识,且需要完全匹配。

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

TEXT_CONTAINS

TEXT 相同,但指定的 VALUE 只需出现在要匹配的元素文本内的某个位置即可。

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

说明

通过内容描述属性识别元素,要求完全匹配。

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

RESOURCE_ID

通过资源 ID 识别元素,并可选择检查该 ID 的软件包组件。PACKAGE 键是可选的;如果省略,则任何软件包都将匹配,并且仅考虑 :id/ 后面的 ID 部分。

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

CLICKABLE, SCROLLABLE

根据元素是否可点击或可滚动来识别元素。这些元素类型非常宽泛,通常应仅在 MULTIPLE 中使用,以帮助缩小其他元素类型的范围。FLAG 键是可选的,默认是 true

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

CLASS

根据元素的类来识别元素。

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

HAS_ANCESTOR

通过查找其祖先的 widget 层次结构来识别元素。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"
      }
    }

MULTIPLE

根据多个同时满足的条件来识别元素,并且必须满足所有这些条件。

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

在此示例中,配置会识别深度为 2 且包含文本 Permission manager 的子项的 RelativeLayout

Workflows

工作流代表用于完成特定任务的一系列操作,这些操作可能因设备类型而异,并且在配置中的表示方式比在代码中更灵活。

    "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_CONFIGSCROLL_CONFIG。对于大多数 TYPE,CONFIG 是一个具有 UI_ELEMENT 键的对象,其值采用与界面元素条目相同的形式(参见上文)。这些类型包括:

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

对于其他 TYPE,配置详情如下:

对象 说明
COMMAND 一个具有 TEXT 值的对象,值包含要执行的命令。
HAS_PACKAGE_IN_FOREGROUND 一个具有 TEXT 值的对象,值含有软件包。
SWIPE 对于 SWIPE 操作,请省略 CONFIG key。此方法仅使用 SWIPE_CONFIG
WAIT_MS 一个具有 TEXT 值的对象,值包含要等待的毫秒数。

与滚动和滑动相关的操作需要进行额外的配置,如下所示:

SCROLL_CONFIG

对象 说明
SCROLL_ACTION USE_GESTUREUSE_BUTTON
SCROLL_DIRECTION HORIZONTALVERTICAL
SCROLL_ELEMENT 一个对象,该对象使用与界面元素配置相同的形式,指示要滚动的容器(参见上文)。
SCROLL_FORWARDSCROLL_BACKWARD 前进和后退滚动按钮(当 SCROLL_ACTIONUSE_BUTTON 时,此项为必需)。
SCROLL_MARGIN 如果 SCROLL_ACTIONUSE_GESTURE,则表示在与容器边缘间隔一定距离时开始和停止拖动,以便执行滚动操作(可选,默认值为 10)。
SCROLL_WAIT_TIME 如果 SCROLL_ACTIONUSE_GESTURE,则表示在搜索要点击的对象时,两次滚动手势之间要等待的时长(以毫秒为单位)。(可选,默认值为 1)。

SWIPE_CONFIG

对象 说明
SWIPE_DIRECTION TOP_TO_BOTTOMBOTTOM_TO_TOPLEFT_TO_RIGHTRIGHT_TO_LEFT
SWIPE_FRACTION

下列各项之

  • FULL:从屏幕边缘滑动到屏幕边缘

    或者
  • DEFAULT:屏幕边缘到屏幕边缘,每侧有五 (5) 像素缓冲区。

  • THREE_QUARTERHALFQUARTER:滑动手势从距离屏幕边缘 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 便可测试 Android.bp 文件中指定的 Wi-Fi 设置。您可以在 Automotive 测试对应的 Android.bp 文件中找到 APK 的名称。

  • DEVICE-SERIAL:DUT 的序列号。如果只有 1 部设备连接到宿主机,则无需使用此参数。

  • config-file-path:可选参数,只有在按 JSON 配置文件中指定的方式提供非默认设备界面配置时才需要使用。如果未提供该参数,则 Spectatio 框架会使用默认值来执行测试。

  • PATH-FOR-BUILT-TEST-APK:系统在执行 make 命令时构建测试 APK 的路径。

  • TEST-PACKAGE:测试软件包的名称。

  • TEST-CLASSNAME:测试类的名称。例如,对于 Wi-Fi 设置测试,测试软件包的名称为 android.platform.tests,测试类的名称为 WifiSettingTest

汽车代码段库

Automotive Snippet Library 是一组适用于 Android 开源项目 (AOSP) 的 Android 测试库,旨在与汽车应用和服务交互。它利用 Spectatio 提供的便捷机制,从宿主机(测试)机器向搭载 Android 的设备执行远程过程调用 (RPC)。

开始使用

在开始之前,请先查看以下部分。

前提条件

  • 在宿主机上安装了 Python 3.x。
  • 带有必要构建工具的 AOSP 环境设置。
  • 一部具有 adb 访问权限的 Android 汽车设备(模拟器或实体设备)。

编译

如需编译 Automotive Snippet 库提供的各种代码段,您可以使用提供的 android.bp 文件。按照上一部分中的命令编译 APK。

部署

成功编译代码段库后,使用上一部分中提到的 adb install 命令将生成的 APK 部署到目标设备。

运行测试

这些代码段库公开了多种 RPC 方法来与汽车系统进行交互。这些方法可通过宿主机中的 Mobly 框架进行调用。假设您已设置 Mobly 测试环境,则可以使用 snippet_shell.py 脚本打开交互式 Python shell,然后您可从中手动在设备上调用 RPC 方法。示例调用:

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

<serial> 替换为设备序列号,如果连接了多个设备,您可以使用 adb 设备获取该序列号。

包含的库

Automotive Snippet 库包含以下代码段库和帮助程序:

  • AutomotiveSnippet:提供与车辆操作相关的 API,例如拨号、音量控制、车辆硬按键和媒体中心互动。

  • PhoneSnippet:提供与电话相关的 API,包括通话处理、浏览联系人和短信操作。

Automotive 代码段和 PhoneSnippet 共享一些常见逻辑。具体而言,您可以入侵与蓝牙相关的 RCP 调用,以配对汽车设备和手机设备。此 bt_discovery_test 演示了操作方法。