Spectatio là một khung kiểm thử nguồn mở được phát triển để kiểm thử Android Automotive OS (AAOS) trên các thiết bị thực và ảo. Spectatio cung cấp các API để kiểm thử ứng dụng trên thiết bị ô tô. Đây là một giải pháp có thể mở rộng và mở rộng, dùng để xác minh chức năng và hiệu suất của AAOS cũng như các ứng dụng của AAOS.
Thiết kế cao cấp
Khung Spectatio có thể thích ứng và mở rộng cho nhiều cách triển khai giao diện người dùng AAOS. API này dùng để kiểm thử chức năng và hiệu suất của AAOS trên phần cứng thiết bị, trình mô phỏng và môi trường ảo hoá.
Hình sau đây giải thích thiết kế cấp cao của khung Spectatio.
Hình 1. Thiết kế cấp cao của khung Spectatio.
Được xây dựng dựa trên Công cụ tự động hoá giao diện người dùng, khung Spectatio cung cấp một bộ API để tạo các chương trình kiểm thử giao diện người dùng tương tác với ứng dụng người dùng và ứng dụng hệ thống trên AAOS. Các chương trình kiểm thử trong ngành ô tô sử dụng các API do khung Spectatio cung cấp để kiểm thử, nhờ đó, các chương trình kiểm thử này độc lập với thiết bị đang được kiểm thử (DUT) và có thể mở rộng để kiểm thử nhiều thiết bị (nếu được hỗ trợ).
Hình 1 cho thấy khung Spectatio được mô-đun hoá dựa trên các ứng dụng tham chiếu như Trình quay số, Trung tâm y tế và Cài đặt bằng cách sử dụng các giao diện và trình trợ giúp dành riêng cho ứng dụng, giúp dễ dàng mở rộng cho các ứng dụng mới. Khung Spectatio sử dụng lại các lớp trợ giúp tiện ích và tiêu chuẩn phổ biến. Lớp trợ giúp chuẩn là lớp mẹ cho tất cả các hàm trợ giúp ứng dụng và cung cấp các hàm chuẩn dành riêng cho thiết bị hoặc áp dụng trên các ứng dụng. Các lớp trình trợ giúp tiện ích cung cấp các tiện ích như đọc hoặc ghi tệp trên thiết bị.
Kiến trúc
Để cung cấp một bộ API nhằm xây dựng các chương trình kiểm thử giao diện người dùng, khung Spectatio triển khai các giao diện và trình trợ giúp dành riêng cho ứng dụng, đồng thời mở rộng lớp trình trợ giúp tiêu chuẩn hiện có và nhập các lớp trình trợ giúp tiện ích.
Hình 2 minh hoạ kiến trúc cấp cao của khung Spectatio và tất cả các thực thể liên quan đến việc triển khai API để kiểm thử ứng dụng.
Hình 2. Cấu trúc cấp cao của khung Spectatio.
Giao diện trình trợ giúp ứng dụng cung cấp bản thiết kế để triển khai trình trợ giúp ứng dụng. Thư viện này bao gồm nhiều hàm trợ giúp cần thiết để kiểm thử ứng dụng. Mỗi ứng dụng đều có giao diện riêng, chẳng hạn như IAutoSettingHelper
và IAutoDialHelper
.
Để biết thêm thông tin và danh sách các hàm giao diện, hãy xem các hàm giao diện trình trợ giúp ứng dụng trên AOSP.
Lớp trình trợ giúp chuẩn bao gồm các thuộc tính và hàm chuẩn cần thiết để thiết lập thiết bị nhưng không dành riêng cho ứng dụng nào, chẳng hạn như pressHome
và scroll
. Lớp trình trợ giúp chuẩn được xác định trong AbstractAutoStandardAppHelper.java
.
Khung này sử dụng các lớp trình trợ giúp tiện ích. Ví dụ: AutoJsonUtility.java
là một lớp tiện ích tải tệp cấu hình JSON của thiết bị đã cho và cập nhật cấu hình khung trong thời gian chạy.
Mô-đun triển khai trình trợ giúp ứng dụng là cốt lõi của khung Spectatio. Tệp này chứa nội dung triển khai cho các hàm trợ giúp được xác định trong giao diện trình trợ giúp ứng dụng, cần thiết để kiểm thử ứng dụng trên thiết bị ô tô. Mỗi ứng dụng có cách triển khai riêng, chẳng hạn như SettingHelperImpl
và DialHelperImpl
mà các bài kiểm thử Automotive sử dụng để kiểm thử ứng dụng. Để biết thêm thông tin và danh sách các cách triển khai, hãy xem các hàm triển khai trình trợ giúp ứng dụng trên AOSP.
Công cụ Kiểm thử Automotive dùng các chức năng triển khai trình trợ giúp ứng dụng để kiểm thử nhiều hoạt động liên quan đến ứng dụng. Hãy dùng lớp HelperAccessor
để có quyền truy cập vào các chức năng triển khai của trình trợ giúp ứng dụng.
Mã sau đây cho thấy cách thiết lập, dọn dẹp và thực thi một quy trình kiểm thử ô tô mẫu.
@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());
}
}
Tuỳ chỉnh
Khung Spectatio độc lập với giao diện người dùng của thiết bị, vì vậy, khung này có thể mở rộng để kiểm thử các thiết bị có nhiều giao diện người dùng và phần cứng. Để đạt được khả năng mở rộng này, Spectatio sử dụng cấu hình thiết bị mặc định dựa trên thiết bị tham chiếu. Để hỗ trợ các cấu hình thiết bị không phải mặc định, khung này sử dụng tệp cấu hình JSON trong thời gian chạy để đặt các thay đổi giao diện người dùng mong muốn cho thiết bị. Tệp cấu hình JSON hỗ trợ các thành phần giao diện người dùng như TEXT
, DESCRIPTION
và RESOURCE_ID
, cùng với các chế độ cài đặt path
và chỉ được chứa thông tin về các thay đổi đối với giao diện người dùng cho DUT. Các phần tử giao diện người dùng còn lại sử dụng giá trị cấu hình mặc định được cung cấp trong khung.
Cấu hình thiết bị mặc định
Tệp cấu hình JSON mẫu sau đây cho thấy các cấu hình thiết bị hiện có và giá trị mặc định của các cấu hình đó.
Nhấp vào đây để hiển thị tệp cấu hình JSON mẫu
{ "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" } } } }
Cấu hình thiết bị thay thế
Đoạn mã mẫu sau đây cho thấy ví dụ về tệp cấu hình JSON, trong đó các chế độ cài đặt mặc định bị ghi đè bởi các chế độ cài đặt trên DUT. Trong ví dụ này:
Chế độ cài đặt Internet có tên là Mạng và Internet trên thiết bị tham chiếu và Kết nối trên thiết bị được kiểm thử (DUT).
Bạn có thể tìm thấy chế độ cài đặt ngày và giờ tại Cài đặt > Ngày và giờ cho thiết bị tham chiếu và tại Cài đặt > Hệ thống > Ngày và giờ cho thiết bị được kiểm thử (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"
},
....
}
Khi tệp cấu hình JSON đã sẵn sàng, tệp này sẽ được cung cấp trong thời gian chạy như trong khối mã sau:
# Push The JSON configuration file to the device
adb -s DEVICE-SERIAL push PATH-OF-JSON-FILE /data/local/tmp/runtimeSpectatioConfig.json
Trong lệnh này:
DEVICE-SERIAL: Mã nhận dạng theo thứ tự của DUT. Bạn không bắt buộc phải sử dụng tham số này nếu chỉ có một thiết bị kết nối với máy chủ.
PATH-TO-JSON-FILE: Đường dẫn của tệp JSON trên máy chủ.
Định dạng cấu hình
Có 5 đối tượng cấp cao nhất trong cấu hình, với các khoá và giá trị sau:
Đối tượng | Mô tả |
---|---|
PACKAGES |
Một đối tượng mô tả gói chính cho nhiều ứng dụng, được dùng để xác định thời điểm ứng dụng đó chạy ở nền trước. |
ACTIONS |
Một đối tượng cho biết các loại hành động và tham số cho nhiều hành động. Ví dụ: sử dụng nút hay cử chỉ để cuộn. |
COMMANDS |
Một đối tượng chỉ định các lệnh thực hiện nhiều hành động. |
UI_ELEMENTS |
Một đối tượng dùng để tạo "BySelectors" (Trình tự động hoá giao diện người dùng) "BySelectors" (Trình tự động hoá giao diện người dùng) chọn các phần tử trên giao diện người dùng (được mô tả chi tiết bên dưới). |
WORKFLOWS |
Trình tự các hành động giúp hoàn thành các tác vụ cấp cao (được mô tả chi tiết bên dưới). |
Phần tử trên giao diện người dùng
Mỗi thành phần trên giao diện người dùng có một TYPE
chỉ định nội dung mà Trình tự động hoá giao diện người dùng sẽ tìm kiếm để xác định thành phần đó (chẳng hạn như mã nhận dạng tài nguyên, văn bản và nội dung mô tả) và các giá trị cấu hình liên kết với loại đó. Nhìn chung, bất cứ khi nào một trình trợ giúp xác định một phần tử trên màn hình bằng cấu hình này, trình trợ giúp đó sẽ nhận được đúng một phần tử. Nếu nhiều phần tử khớp với cấu hình, thì một phần tử tuỳ ý sẽ được sử dụng trong kiểm thử. Do đó, cấu hình (thường) phải được viết một cách cụ thể để thu hẹp thành một phần tử trong ngữ cảnh có liên quan.
VĂN BẢN
Đây là loại thành phần giao diện người dùng đơn giản nhất. Phần tử trên giao diện người dùng được xác định bằng văn bản và yêu cầu khớp chính xác.
"CALL_HISTORY_MENU": {
"TYPE": "TEXT",
"VALUE": "Recents"
}
TEXT_CONTAINS
Tương tự như TEXT
, ngoại trừ việc VALUE
được chỉ định chỉ cần xuất hiện ở đâu đó trong văn bản của phần tử cần so khớp.
"PRIVACY_CALENDAR": {
"TYPE": "TEXT_CONTAINS",
"VALUE": "Calendar"
}
NỘI DUNG MÔ TẢ
Xác định phần tử theo thuộc tính mô tả nội dung, yêu cầu khớp chính xác.
"APP_GRID_SCROLL_BACKWARD_BUTTON": {
"TYPE": "DESCRIPTION",
"VALUE": "Scroll up"
}
RESOURCE_ID
Xác định phần tử theo mã nhận dạng tài nguyên, cũng như kiểm tra thành phần gói của mã nhận dạng đó (không bắt buộc). Khoá PACKAGE
là không bắt buộc; nếu bị bỏ qua, mọi gói sẽ khớp và chỉ phần mã nhận dạng theo sau :id/
mới được xem xét.
"APP_LIST_SCROLL_ELEMENT": {
"TYPE": "RESOURCE_ID",
"VALUE": "apps_grid",
"PACKAGE": "com.android.car.carlauncher"
}
CÓ THỂ NHẤP CHUỘT, CÓ THỂ CUỘC
Xác định phần tử dựa trên việc phần tử đó có thể nhấp (hoặc không thể nhấp) hoặc có thể cuộn (hoặc không thể cuộn) hay không.
Đây là những loại phần tử rất rộng và thường chỉ nên được dùng trong MULTIPLE
để giúp thu hẹp một loại phần tử khác. Khoá FLAG
là không bắt buộc và mặc định là true
.
"SAMPLE_ELEMENT": {
"TYPE": "CLICKABLE",
"FLAG": false
}
LỚP
Xác định phần tử dựa trên lớp của phần tử đó.
"SECURITY_SETTINGS_ENTER_PASSWORD": {
"TYPE": "CLASS",
"VALUE": "android.widget.EditText"
}
HAS_ANCESTOR
Xác định phần tử bằng cách tra cứu hệ phân cấp tiện ích ở các phần tử mẹ. Khoá ANCESTOR
chứa một đối tượng xác định đối tượng cấp trên. Khoá DEPTH
chỉ định khoảng cách xem hệ phân cấp. DEPTH
là không bắt buộc và có giá trị mặc định là 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_ANCESTOR",
"DEPTH": 2,
"ANCESTOR": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
HAS_DESCENDANT
Xác định phần tử bằng cách xem hệ phân cấp của các phần tử con. Khoá DESCENDANT
chứa một đối tượng chỉ định phần tử con cần tìm. Khoá DEPTH
chỉ định khoảng cách xem trong hệ phân cấp. DEPTH
là không bắt buộc và có giá trị mặc định là 1
.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_DESCENDANT",
"DEPTH": 2,
"DESCENDANT": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
NHIỀU
Xác định phần tử dựa trên nhiều điều kiện đồng thời, tất cả điều kiện đó đều phải được đáp ứng.
"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"
}
}
]
}
Trong ví dụ này, cấu hình xác định một RelativeLayout
có một phần tử con ở độ sâu 2
, có văn bản Permission manager
.
Workflows
Quy trình công việc biểu thị một chuỗi hành động dùng để hoàn thành một tác vụ cụ thể, có thể khác nhau đủ giữa loại thiết bị và loại thiết bị và linh hoạt hơn để thể hiện trong cấu hình so với trong mã.
"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"
}
}
}
]
}
Mỗi quy trình công việc là một cặp khoá-giá trị, trong đó khoá là tên của quy trình công việc và giá trị là một mảng các thao tác cần thực hiện. Mỗi thao tác có một NAME
, một TYPE
, (thường là) một CONFIG
và (đôi khi) một SWIPE_CONFIG
hoặc SCROLL_CONFIG
. Đối với hầu hết các TYPE, CONFIG
là một đối tượng có khoá UI_ELEMENT
, giá trị của khoá này có cùng dạng với mục nhập phần tử giao diện người dùng (xem ở trên). Đó là:
Nhấn Nhấn_lâu Nhấp Nhấp_lâu Nhấp_nếu_có |
Đối với các LOẠI khác, thông tin chi tiết về cấu hình là:
Đối tượng | Mô tả |
---|---|
COMMAND |
Một đối tượng có giá trị TEXT chứa lệnh để thực thi. |
HAS_PACKAGE_IN_FOREGROUND |
Một đối tượng có giá trị TEXT chứa gói. |
SWIPE |
Bỏ qua CONFIG key cho thao tác SWIPE . Phương thức này chỉ sử dụng SWIPE_CONFIG |
WAIT_MS |
Một đối tượng có giá trị TEXT chứa số mili giây cần chờ. |
Các thao tác liên quan đến thao tác cuộn và vuốt yêu cầu phải định cấu hình thêm như sau:
SCROLL_CONFIG
Đối tượng | Mô tả |
---|---|
SCROLL_ACTION |
USE_GESTURE hoặc USE_BUTTON |
SCROLL_DIRECTION |
HORIZONTAL hoặc VERTICAL |
SCROLL_ELEMENT |
Một đối tượng cho biết vùng chứa cần cuộn, sử dụng cùng một hình thức với cấu hình Phần tử giao diện người dùng (xem ở trên). |
SCROLL_FORWARD , SCROLL_BACKWARD |
Các nút cuộn tiến và lùi (bắt buộc khi SCROLL_ACTION là USE_BUTTON ). |
SCROLL_MARGIN |
Nếu SCROLL_ACTION là USE_GESTURE , thì khoảng cách từ cạnh của vùng chứa để bắt đầu và dừng thao tác kéo sẽ được dùng để thực hiện thao tác cuộn (Không bắt buộc, mặc định = 10). |
SCROLL_WAIT_TIME |
Nếu SCROLL_ACTION là USE_GESTURE , thời gian tính bằng mili giây để chờ giữa các cử chỉ cuộn khi tìm kiếm một đối tượng để nhấp vào.
(Không bắt buộc, mặc định = 1). |
SWIPE_CONFIG
Đối tượng | Mô tả |
---|---|
SWIPE_DIRECTION |
TOP_TO_BOTTOM , BOTTOM_TO_TOP , LEFT_TO_RIGHT hoặc RIGHT_TO_LEFT |
SWIPE_FRACTION |
Một trong các trường hợp sau:
|
NUMBER_OF_STEPS |
Số bước sẽ được dùng để thực hiện thao tác vuốt. Hãy xem
segmentSteps .
|
Tạo bản dựng và thực thi
Khung Spectatio được tạo tự động trong tệp APK kiểm thử. Để tạo tệp APK kiểm thử, cơ sở mã AOSP phải nằm trên máy trạm cục bộ. Sau khi tạo APK kiểm thử, người dùng phải cài đặt APK trên thiết bị và thực thi kiểm thử.
Mã mẫu sau đây cho thấy quá trình tạo, cài đặt và thực thi APK kiểm thử.
# 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
Trong các lệnh này:
TEST-APK-NAME: Tên của ứng dụng cần kiểm thử. Ví dụ: đặt TEST-APK-NAME thành
AndroidAutomotiveSettingsTests
để kiểm thử chế độ cài đặt Wi-Fi như được chỉ định trong tệpAndroid.bp
. Bạn có thể tìm thấy tên của tệp APK trong tệpAndroid.bp
tương ứng cho Kiểm thử ô tô.DEVICE-SERIAL: Mã sê-ri của DUT. Bạn không bắt buộc phải sử dụng tham số này nếu chỉ có một thiết bị được kết nối với máy chủ.
config-file-path
: Tham số không bắt buộc chỉ cần thiết để cung cấp cấu hình giao diện người dùng thiết bị không mặc định như được chỉ định trong tệp cấu hình JSON. Nếu không được cung cấp, khung này sẽ sử dụng các giá trị mặc định để thực thi kiểm thử.PATH-FOR-BUILT-TEST-APK: Đường dẫn nơi tạo APK kiểm thử khi lệnh
make
được thực thi.TEST-PACKAGE: Tên của gói kiểm thử.
TEST-CLASSNAME: Tên của lớp kiểm thử. Ví dụ: đối với kiểm thử Wifi Settings (Cài đặt Wi-Fi), gói kiểm thử là
android.platform.tests
và tên lớp kiểm thử làWifiSettingTest
.
Thư viện đoạn mã dành cho ô tô
Thư viện đoạn mã dành cho ô tô là một nhóm thư viện Kiểm thử Android dành cho Dự án nguồn mở Android (AOSP) được thiết kế để tương tác với các ứng dụng và dịch vụ dành cho ô tô. Thư viện này tận dụng Spectatio bằng một cơ chế thuận tiện để thực thi các lệnh gọi quy trình từ xa (RPC) từ một máy chủ lưu trữ (kiểm thử) đến một thiết bị chạy Android.
Bắt đầu
Trước khi bắt đầu, hãy xem lại các phần sau.
Điều kiện tiên quyết
- Python 3.x đã được cài đặt trên máy chủ lưu trữ.
- Thiết lập môi trường AOSP bằng các công cụ xây dựng cần thiết.
- Thiết bị Android Automotive (trình mô phỏng hoặc thiết bị thực) có quyền truy cập adb.
Biên dịch
Để biên dịch nhiều đoạn mã do Thư viện đoạn mã Automotive cung cấp, bạn có thể sử dụng tệp android.bp
được cung cấp. Thực hiện các lệnh trong phần trước để biên dịch APK.
Triển khai
Sau khi biên dịch thành công các thư viện đoạn mã, hãy triển khai các tệp APK thu được cho thiết bị mục tiêu bằng lệnh adb install
được đề cập trong phần trước.
Chạy chương trình kiểm thử
Thư viện đoạn mã hiển thị một số phương thức RPC để tương tác với hệ thống ô tô. Bạn có thể gọi các phương thức này thông qua khung Mobly từ máy chủ. Giả sử bạn đã thiết lập môi trường kiểm thử Mobly, bạn có thể sử dụng tập lệnh snippet_shell.py
để mở một shell Python tương tác, trong đó bạn có thể gọi các phương thức RPC theo cách thủ công trên thiết bị. Ví dụ về lệnh gọi:
python3 snippet_shell.py com.google.android.mobly.snippet.bundled -s <serial>
Thay thế <serial>
bằng số sê-ri của thiết bị mà bạn có thể lấy bằng thiết bị adb nếu có nhiều thiết bị được kết nối.
Thư viện đi kèm
Thư viện đoạn mã Automotive bao gồm các thư viện đoạn mã và trình trợ giúp sau:
AutomotiveSnippet: Cung cấp các API liên quan đến hoạt động của xe, chẳng hạn như gọi điện, điều khiển âm lượng, nút cứng trên xe và tương tác với trung tâm đa phương tiện.
PhoneSnippet: Cung cấp các API liên quan đến điện thoại, bao gồm cả việc xử lý cuộc gọi, duyệt danh bạ và thao tác với tin nhắn SMS.
Đoạn mã Automotive và Đoạn mã điện thoại có chung một số logic.
Cụ thể, bạn có thể xâm nhập vào các lệnh gọi RCP liên quan đến Bluetooth để ghép nối thiết bị ô tô và điện thoại. bt_discovery_test
này cho thấy cách thực hiện.
- TEST-CLASSNAME: Tên của lớp kiểm thử. Ví dụ: đối với kiểm thử Wifi Settings (Cài đặt Wi-Fi), gói kiểm thử là
android.platform.tests
và tên lớp kiểm thử làWifiSettingTest
.