Spectatio یک چارچوب تست منبع باز است که برای آزمایش سیستم عامل Android Automotive (AAOS) در دستگاه های واقعی و مجازی توسعه یافته است. Spectatio API هایی را برای آزمایش برنامه ها در دستگاه خودرو ارائه می دهد و راه حلی قابل گسترش و مقیاس پذیر است که برای تأیید قابلیت و عملکرد AAOS و برنامه های آن استفاده می شود.
طراحی سطح بالا
چارچوب Spectatio برای پیاده سازی های مختلف AAOS UI قابل انطباق و گسترش است. برای آزمایش قابلیت و عملکرد AAOS بر روی سخت افزار دستگاه، شبیه سازها و محیط های مجازی استفاده می شود.
شکل زیر طراحی سطح بالای چارچوب Spectatio را توضیح می دهد.
شکل 1. طراحی سطح بالا چارچوب Spectatio.
چارچوب Spectatio که در بالای UI Automator ساخته شده است، مجموعهای از APIها را برای ساخت تستهای UI ارائه میکند که با کاربر و برنامههای سیستم در AAOS تعامل دارند. تستهای خودرو از APIهای ارائهشده توسط چارچوب Spectatio برای آزمایش استفاده میکنند، که این تستها را مستقل از دستگاه تحت آزمایش (DUT) و مقیاسپذیر برای آزمایش دستگاههای مختلف، در صورت پشتیبانی میکند.
شکل 1 نشان میدهد که چارچوب Spectatio بر اساس برنامههای مرجع مانند Dialer، Medicenter و Settings با استفاده از رابطها و کمککنندههای خاص برنامه، مدولار شده است و به راحتی برای برنامههای جدید قابل گسترش است. چارچوب Spectatio از کلاسهای کمکی استاندارد و کاربردی مجدد استفاده میکند. کلاس کمکی استاندارد، کلاس والد برای همه توابع کمکی برنامه است و عملکردهای استانداردی را ارائه میکند که مخصوص دستگاه هستند یا در بین برنامهها قابل اجرا هستند. کلاس های کمکی ابزارهایی مانند خواندن یا نوشتن فایل ها از دستگاه را ارائه می دهند.
معماری
برای ارائه مجموعهای از APIها برای ساخت تستهای UI، چارچوب Spectatio رابطها و کمکهای مخصوص اپلیکیشن را پیادهسازی میکند، در حالی که کلاس کمکی استاندارد موجود را گسترش میدهد و کلاسهای کمکی ابزار را وارد میکند.
شکل 2 معماری سطح بالای چارچوب Spectatio و تمام نهادهای درگیر در اجرای APIها برای آزمایش یک برنامه را نشان می دهد.
شکل 2. معماری سطح بالا چارچوب Spectatio.
رابط برنامه کمکی طرحی را برای اجرای یک برنامه کمکی ارائه می دهد. این شامل توابع کمکی مختلفی است که برای آزمایش برنامه ها مورد نیاز است. هر برنامه رابط مخصوص به خود را دارد، مانند IAutoSettingHelper
و IAutoDialHelper
. برای اطلاعات بیشتر و لیستی از عملکردهای رابط، به توابع رابط کمکی برنامه در AOSP مراجعه کنید.
کلاس کمکی استاندارد شامل ویژگیها و عملکردهای استانداردی است که برای راهاندازی دستگاه مورد نیاز هستند، اما مختص هیچ برنامهای نیستند، مانند pressHome
و scroll
. کلاس کمکی استاندارد در AbstractAutoStandardAppHelper.java
تعریف شده است.
کلاس های کمکی توسط فریمورک استفاده می شود. به عنوان مثال، AutoJsonUtility.java
یک کلاس ابزار است که فایل پیکربندی JSON دستگاه داده شده را بارگیری می کند و پیکربندی های چارچوب را در زمان اجرا به روز می کند.
ماژول اجرای برنامه کمکی هسته چارچوب Spectatio است. این شامل پیاده سازی برای توابع کمکی تعریف شده در رابط برنامه کمکی است که برای آزمایش برنامه ها در یک دستگاه خودرو مورد نیاز است. هر برنامه پیادهسازی خاص خود را دارد، مانند SettingHelperImpl
و DialHelperImpl
که توسط تستهای Automotive برای آزمایش برنامهها استفاده میشوند. برای اطلاعات بیشتر و لیستی از پیاده سازی ها، به توابع پیاده سازی کمک کننده برنامه در AOSP مراجعه کنید.
Automotive Tests از توابع اجرای برنامه کمکی برای آزمایش عملیات مختلف مرتبط با برنامه استفاده می کند. از کلاس 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 در زمان اجرا استفاده میکند تا تغییرات UI مورد نظر را برای دستگاه تنظیم کند. یک فایل پیکربندی JSON از عناصر رابط کاربری مانند TEXT
، DESCRIPTION
، و RESOURCE_ID
به همراه تنظیمات path
پشتیبانی میکند و باید فقط حاوی اطلاعات مربوط به تغییرات UI برای DUT باشد. بقیه عناصر UI از مقادیر پیکربندی پیش فرض ارائه شده در چارچوب استفاده می کنند.
تنظیمات پیش فرض دستگاه
نمونه فایل پیکربندی 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 نامیده می شوند.
تنظیمات تاریخ و زمان در Settings > Date and time برای دستگاه های مرجع و در Settings > System > Date and time برای 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. اگر فقط یک دستگاه به میزبان متصل باشد، این پارامتر مورد نیاز نیست.
PATH-TO-JSON-FILE : مسیر فایل JSON در دستگاه میزبان.
فرمت پیکربندی
پنج شی سطح بالا در پیکربندی وجود دارد، با کلیدها و مقادیر زیر:
شیء | توضیحات |
---|---|
PACKAGES | یک شی که بسته اصلی را برای برنامه های مختلف توصیف می کند، که برای تعیین زمانی که آن برنامه در پیش زمینه است استفاده می شود. |
ACTIONS | یک شی که انواع و پارامترهای عملکرد را برای اقدامات مختلف نشان می دهد. به عنوان مثال، اینکه آیا از دکمه ها استفاده کنید یا از یک حرکت برای پیمایش. |
COMMANDS | شی ای که دستوراتی را مشخص می کند که اعمال مختلفی را انجام می دهد. |
UI_ELEMENTS | شیء مورد استفاده برای ساخت UI Automator «BySelectors» که عناصر UI را انتخاب می کند (در جزئیات در زیر توضیح داده شده است). |
WORKFLOWS | دنباله ای از اقداماتی که وظایف سطح بالا را انجام می دهند (به تفصیل در زیر توضیح داده شده است). |
عناصر رابط کاربری
هر عنصر UI دارای TYPE
است که مشخص می کند UI Automator برای شناسایی عنصر (مانند شناسه منبع، متن و توضیحات) و مقادیر پیکربندی مرتبط با آن نوع به دنبال چه چیزی خواهد بود. به طور کلی، هر زمان که یک کمک کننده با استفاده از این پیکربندی، عنصری را روی صفحه شناسایی کند، دقیقاً یک عنصر را دریافت می کند. اگر چندین عنصر با پیکربندی مطابقت داشته باشند، یک عنصر دلخواه در آزمایش استفاده می شود. بنابراین، پیکربندی باید (به طور کلی) به طور خاص به اندازه کافی نوشته شود که به یک عنصر در زمینه مربوطه محدود شود.
TEXT
این ساده ترین نوع عنصر رابط کاربری است. عنصر UI با متن آن مشخص می شود و به تطابق دقیق نیاز دارد.
"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
عنصر را با شناسه منبع آن شناسایی کنید، همچنین به صورت اختیاری جزء بسته آن شناسه را نیز بررسی کنید. کلید 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"
}
دارای اجداد
با جستجوی سلسله مراتب ویجت در اجداد آن، عنصر را شناسایی کنید. کلید 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
است که مقدار آن به شکل ورودی عنصر UI است (به بالا مراجعه کنید). آن انواع عبارتند از:
را فشار دهید 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_CONFIG
شیء | توضیحات |
---|---|
SCROLL_ACTION | USE_GESTURE یا USE_BUTTON |
SCROLL_DIRECTION | HORIZONTAL یا VERTICAL |
SCROLL_ELEMENT | یک شی که نشان می دهد ظرف برای پیمایش، با استفاده از همان فرم پیکربندی عنصر UI (به بالا مراجعه کنید). |
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 | یکی از موارد زیر:
|
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
مربوطه برای تست Automotive پیدا کنید.DEVICE-SERIAL : شناسه سریال DUT. اگر فقط یک دستگاه به هاست متصل باشد، این پارامتر مورد نیاز نیست.
config-file-path
: پارامتر اختیاری که فقط برای ارائه تنظیمات رابط کاربری غیر پیشفرض دستگاه همانطور که در فایل پیکربندی JSON مشخص شده است، مورد نیاز است. در صورت عدم ارائه، چارچوب از مقادیر پیش فرض برای اجرای تست ها استفاده می کند.PATH-FOR-BUILT-TEST-APK : مسیری که در آن APK آزمایشی هنگام اجرای دستور
make
ساخته می شود.TEST-PACKAGE : نام بسته آزمایشی.
TEST-CLASSNAME : نام کلاس آزمایشی. به عنوان مثال، برای تست تنظیمات Wifi ، بسته آزمایشی
android.platform.tests
و نام کلاس تستWifiSettingTest
است.
کتابخانه قطعه خودرو
Automotive Snippet Library مجموعه ای از کتابخانه های تست اندروید برای پروژه متن باز اندروید (AOSP) است که برای تعامل با برنامه ها و سرویس های خودرو طراحی شده است. این دستگاه از Spectatio با مکانیزمی مناسب برای اجرای تماسهای رویه از راه دور (RPC) از یک دستگاه میزبان (تست) به یک دستگاه مجهز به اندروید بهره میبرد.
شروع کنید
قبل از شروع، این بخش ها را مرور کنید.
پیش نیازها
- پایتون 3.x روی دستگاه میزبان نصب شده است.
- راه اندازی محیط AOSP با ابزارهای ساخت لازم.
- یک دستگاه خودروی اندروید (شبیه ساز یا دستگاه فیزیکی) با دسترسی adb.
تالیف
برای کامپایل قطعه های مختلف ارائه شده توسط Automotive Snippet Library، می توانید از فایل android.bp
ارائه شده استفاده کنید. دستورات بخش قبل را برای کامپایل APK دنبال کنید.
استقرار
پس از کامپایل موفقیت آمیز کتابخانه های قطعه، APK های حاصل را با استفاده از دستور adb install
که در بخش قبل ذکر شد، در دستگاه مورد نظر مستقر کنید.
تست ها را اجرا کنید
کتابخانه های قطعه چندین روش RPC را برای تعامل با سیستم خودرو در معرض دید قرار می دهند. این روش ها را می توان از طریق چارچوب Mobly از ماشین میزبان فراخوانی کرد. با فرض اینکه محیط تست Mobly را تنظیم کرده اید، می توانید از اسکریپت snippet_shell.py
برای باز کردن یک پوسته تعاملی پایتون استفاده کنید، جایی که می توانید به صورت دستی روش های RPC را در دستگاه فراخوانی کنید. فراخوانی مثال:
python3 snippet_shell.py com.google.android.mobly.snippet.bundled -s <serial>
شماره سریال دستگاه را جایگزین <serial>
کنید، که در صورت اتصال چندین دستگاه می توانید آن را با دستگاه های adb بدست آورید.
شامل کتابخانه ها
کتابخانه قطعه خودرو شامل کتابخانهها و راهنماهای قطعه زیر است:
AutomotiveSnippet: API های مربوط به عملیات خودرو، مانند شماره گیری، کنترل صدا، کلیدهای سخت خودرو و تعامل با مرکز رسانه را ارائه می دهد.
PhoneSnippet: API های مربوط به تلفن، از جمله مدیریت تماس، مرور مخاطبین و عملیات پیام کوتاه را ارائه می دهد.
قطعه Automotive و PhoneSnippet منطق مشترکی دارند. به طور خاص، میتوانید به تماسهای RCP مرتبط با بلوتوث برای جفت کردن یک خودرو و یک دستگاه تلفن حمله کنید. این bt_discovery_test
نشان می دهد که چگونه.
- TEST-CLASSNAME : نام کلاس آزمایشی. به عنوان مثال، برای تست تنظیمات Wifi ، بسته آزمایشی
android.platform.tests
و نام کلاس تستWifiSettingTest
است.