Spectatio هو إطار عمل اختبار مفتوح المصدر تم تطويره لاختبار نظام التشغيل Android Automotive (AAOS) على الأجهزة الحقيقية والافتراضية. توفّر Spectatio واجهات برمجة تطبيقات لاختبار التطبيقات على جهاز سيارة، وهي حلّ قابل للتوسيع والتكيّف يُستخدَم للتحقّق من إمكانات نظام التشغيل Android Automotive وأدائه وتطبيقاته.
التصميم عالي المستوى
يتكيّف إطار عمل Spectatio ويتوسّع مع مختلف عمليات تنفيذ واجهة مستخدم نظام التشغيل Android Automotive. ويُستخدَم لاختبار إمكانات نظام التشغيل Android Automotive وأدائه على أجهزة الجهاز والمحاكيات والبيئات المحاكاة.
يوضّح الشكل التالي التصميم عالي المستوى لإطار عمل Spectatio.
الشكل 1: التصميم عالي المستوى لإطار عمل Spectatio
يستند إطار عمل Spectatio إلى UI Automator، ويوفر مجموعة من واجهات برمجة التطبيقات لإنشاء اختبارات واجهة المستخدم التي تتفاعل مع تطبيقات المستخدم والنظام على نظام التشغيل Android Automotive. تستخدِم اختبارات السيارات واجهات برمجة التطبيقات التي يوفّرها إطار عمل Spectatio للاختبار، ما يجعل هذه الاختبارات مستقلة عن الجهاز قيد الاختبار وقابلة للتوسيع لاختبار أجهزة متنوّعة، إذا كانت متوافقة.
يوضّح الشكل 1 أنّ إطار عمل Spectatio يتم تقسيمه إلى وحدات استنادًا إلى التطبيقات المرجعية، مثل "طلب الهاتف" و"مركز الصيانة" و"الإعدادات"، باستخدام واجهات وأدوات مساعدة خاصة بالتطبيق، ما يجعله قابلاً للتوسيع بسهولة للتطبيقات الجديدة. يعيد إطار عمل Spectatio استخدام الفئات المساعدة الشائعة القياسية والمرافق. فئة المساعد القياسية هي الفئة الرئيسية لجميع دوال المساعد في التطبيق وتوفّر دوال قياسية خاصة بالجهاز أو قابلة للتطبيق على مستوى التطبيقات. توفر الفئات المساعدة للمرافق أدوات مساعدة، مثل قراءة الملفات أو كتابتها من الجهاز.
هندسة معمارية
لتوفير مجموعة من واجهات برمجة التطبيقات لإنشاء اختبارات واجهة المستخدم، ينفّذ إطار عمل Spectatio واجهات وأدوات مساعدة خاصة بالتطبيق مع توسيع فئة المساعد القياسية الحالية واستيراد الفئات المساعدة للمرافق.
يوضّح الشكل 2 البنية عالية المستوى لإطار عمل Spectatio وجميع الكيانات المعنيّة بتنفيذ واجهات برمجة التطبيقات لاختبار تطبيق.
الشكل 2: البنية عالية المستوى لإطار عمل Spectatio
توفّر واجهة المساعد في التطبيق مخططًا لتنفيذ مساعد في التطبيق. وتتألف من دوال مساعدة مختلفة مطلوبة لاختبار التطبيقات. لكل تطبيق واجهة خاصة به، مثل IAutoSettingHelper
وIAutoDialHelper.
لمزيد من المعلومات وقائمة بدوال الواجهة، يُرجى الاطّلاع على دوال واجهة المساعد في التطبيق على AOSP.
تتألف فئة المساعد القياسية من سمات ودوال قياسية مطلوبة لإعداد الجهاز ولكنها ليست خاصة بأي تطبيق، مثل pressHome وscroll. تم تحديد فئة المساعد القياسية في AbstractAutoStandardAppHelper.java.
يستخدم إطار العمل الفئات المساعدة للمرافق . على
سبيلAutoJsonUtility.javaالمثال، هي
فئة مساعدة تحمِّل ملف إعداد JSON المحدّد للجهاز وتعدِّل
إعدادات إطار العمل في وقت التشغيل.
وحدة تنفيذ المساعد في التطبيق هي جوهر إطار عمل Spectatio. تحتوي على تنفيذ الدوال المساعدة المحدّدة في واجهة المساعد في التطبيق، والتي تكون مطلوبة لاختبار التطبيقات على جهاز سيارة. لكل تطبيق عملية تنفيذ خاصة به، مثل SettingHelperImpl
و
DialHelperImpl،
التي تستخدمها
اختبارات السيارات لاختبار التطبيقات. لمزيد من المعلومات وقائمة بعمليات التنفيذ
، يُرجى الاطّلاع على دوال تنفيذ المساعد في التطبيق
'على AOSP.
تستخدِم اختبارات السيارات
دوال تنفيذ المساعد في التطبيق لاختبار عمليات مختلفة
ذات صلة بالتطبيق. استخدِم فئة HelperAccessor
للوصول إلى دوال تنفيذ المساعد في التطبيق.
يعرض الرمز التالي عملية إعداد اختبار سيارة نموذجي وتنظيفه وتنفيذه.
@RunWith(AndroidJUnit4.class)
public class AutoApplicationTest {
static HelperAccessor<IAutoApplicationHelper> autoApplicationHelper =
new HelperAccessor<>(IAutoApplicationHelper.class);
public AutoApplicationTest() {
// constructor
// Initialize any attributes that are required for the test execution
}
@Before
public void beforeTest() {
// Initial setup before each test
// For example - open the app
autoApplicationHelper.open();
}
@After
public void afterTest() {
// Cleanup after each test.
// For example - exit the app
autoApplicationHelper.exit();
}
@Test
public void testApplicationFeature() {
// Test
// For example - Test if app is open
assertTrue("Application is not open.", autoApplicationHelper.isOpen());
}
}
التخصيص
إطار عمل Spectatio مستقل عن واجهة مستخدم الجهاز، لذا فهو قابل للتوسيع لاختبار الأجهزة التي تتضمّن واجهات مستخدم وأجهزة متنوّعة. لتحقيق هذه القابلية للتوسيع، تستخدِم Spectatio إعدادات الجهاز التلقائية استنادًا إلى الجهاز المرجعي. لدعم إعدادات الجهاز غير التلقائية، يستخدم إطار العمل ملف إعداد JSON في وقت التشغيل لضبط التغييرات المطلوبة في واجهة المستخدم للجهاز. يدعم ملف إعداد JSON عناصر واجهة المستخدم، مثل TEXT وDESCRIPTION وRESOURCE_ID، بالإضافة إلى إعدادات path، ويجب أن يحتوي فقط على معلومات حول التغييرات في واجهة المستخدم للجهاز قيد الاختبار. تستخدِم بقية عناصر واجهة المستخدم قيم الإعدادات التلقائية المتوفّرة في إطار العمل.
إعدادات الجهاز التلقائية
يعرض ملف إعداد JSON النموذجي التالي إعدادات الجهاز المتاحة وقيمها التلقائية.
انقر هنا لعرض ملف إعداد JSON نموذجي
{ "SETTINGS": { "APPLICATION_CONFIG": { "SETTINGS_TITLE_TEXT": "Settings", "SETTINGS_PACKAGE": "com.android.car.settings", "SETTINGS_RRO_PACKAGE": "com.android.car.settings.googlecarui.rro", "OPEN_SETTINGS_COMMAND": "am start -a android.settings.SETTINGS", "OPEN_QUICK_SETTINGS_COMMAND": "am start -n com.android.car.settings/com.android.car.settings.common.CarSettingActivity" }, "QUICK_SETTINGS": { "OPEN_MORE_SETTINGS": { "TYPE": "RESOURCE_ID", "VALUE": "toolbar_menu_item_1", "PACKAGE": "com.android.car.settings" }, "NIGHT_MODE": { "TYPE": "TEXT", "VALUE": "Night mode" } }, "DISPLAY": { "PATH": "Settings > Display", "OPTIONS": [ "Brightness level" ], "BRIGHTNESS_LEVEL": { "TYPE": "RESOURCE_ID", "VALUE": "seekbar", "PACKAGE": "com.android.car.settings" } }, "SOUND": { "PATH": "Settings > Sound", "OPTIONS": [ "Media volume", "Alarm volume" ] }, "NETWORK_AND_INTERNET": { "PATH": "Settings > Network & internet", "OPTIONS": [ ], "TOGGLE_WIFI": { "TYPE": "RESOURCE_ID", "VALUE": "master_switch", "PACKAGE": "com.android.car.settings" } }, "BLUETOOTH": { "PATH": "Settings > Bluetooth", "OPTIONS": [ ], "TOGGLE_BLUETOOTH": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_menu_item_switch", "PACKAGE": "com.android.car.settings" } }, "APPS_AND_NOTIFICATIONS": { "PATH": "Settings > Apps & notifications", "OPTIONS": [ ], "SHOW_ALL_APPS": { "TYPE": "TEXT", "VALUE": "Show all apps" }, "ENABLE_DISABLE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_menu_item_text", "PACKAGE": "com.android.car.settings" }, "DISABLE_BUTTON_TEXT": { "TYPE": "TEXT", "VALUE": "Disable" }, "ENABLE_BUTTON_TEXT": { "TYPE": "TEXT", "VALUE": "Enable" }, "DISABLE_APP_BUTTON": { "TYPE": "TEXT", "VALUE": "DISABLE APP" }, "FORCE_STOP_BUTTON": { "TYPE": "TEXT", "VALUE": "Force stop" }, "OK_BUTTON": { "TYPE": "TEXT", "VALUE": "OK" }, "PERMISSIONS_MENU": { "TYPE": "TEXT", "VALUE": "Permissions" }, "ALLOW_BUTTON": { "TYPE": "TEXT", "VALUE": "Allow" }, "DENY_BUTTON": { "TYPE": "TEXT", "VALUE": "Deny" }, "DENY_ANYWAY_BUTTON": { "TYPE": "TEXT", "VALUE": "Deny anyway" } }, "DATE_AND_TIME": { "PATH": "Settings > Date & time", "OPTIONS": [ "Automatic date & time", "Automatic time zone" ], "AUTOMATIC_DATE_AND_TIME": { "TYPE": "TEXT", "VALUE": "Automatic date & time" }, "AUTOMATIC_TIME_ZONE": { "TYPE": "TEXT", "VALUE": "Automatic time zone" }, "SET_DATE": { "TYPE": "TEXT", "VALUE": "Set date" }, "SET_TIME": { "TYPE": "TEXT", "VALUE": "Set time" }, "SELECT_TIME_ZONE": { "TYPE": "TEXT", "VALUE": "Select time zone" }, "USE_24_HOUR_FORMAT": { "TYPE": "TEXT", "VALUE": "Use 24-hour format" }, "OK_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "toolbar_menu_item_0", "PACKAGE": "com.android.car.settings" }, "NUMBER_PICKER_WIDGET": { "TYPE": "CLASS", "VALUE": "android.widget.NumberPicker" }, "EDIT_TEXT_WIDGET": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" } }, "USERS": { "PATH": "Settings > Users", "OPTIONS": [ "Guest" ] }, "ACCOUNTS": { "PATH": "Settings > Accounts", "OPTIONS": [ "Automatically sync data" ], "ADD_ACCOUNT": { "TYPE": "TEXT", "VALUE": "ADD ACCOUNT" }, "ADD_GOOGLE_ACCOUNT": { "TYPE": "TEXT", "VALUE": "Google" }, "SIGN_IN_ON_CAR_SCREEN": { "TYPE": "TEXT", "VALUE": "Sign in on car screen" }, "GOOGLE_SIGN_IN_SCREEN": { "TYPE": "TEXT", "VALUE": "Sign in to your Google Account" }, "ENTER_EMAIL": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" }, "ENTER_PASSWORD": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" }, "NEXT_BUTTON": { "TYPE": "TEXT", "VALUE": "Next" }, "DONE_BUTTON": { "TYPE": "TEXT", "VALUE": "Done" }, "REMOVE_BUTTON": { "TYPE": "TEXT", "VALUE": "Remove" }, "REMOVE_ACCOUNT_BUTTON": { "TYPE": "TEXT", "VALUE": "Remove Account" } }, "SYSTEM": { "PATH": "Settings > System", "OPTIONS": [ "About", "Legal information" ], "ABOUT_MENU": { "TYPE": "TEXT", "VALUE": "About" }, "RESET_OPTIONS_MENU": { "TYPE": "TEXT", "VALUE": "Reset options" }, "LANGUAGES_AND_INPUT_MENU": { "TYPE": "TEXT", "VALUE": "Languages & input" }, "DEVICE_MODEL": { "TYPE": "TEXT", "VALUE": "Model" }, "ANDROID_VERSION": { "TYPE": "TEXT", "VALUE": "Android version" }, "ANDROID_SECURITY_PATCH_LEVEL": { "TYPE": "TEXT", "VALUE": "Android security patch level" }, "KERNEL_VERSION": { "TYPE": "TEXT", "VALUE": "Kernel version" }, "BUILD_NUMBER": { "TYPE": "TEXT", "VALUE": "Build number" }, "RECYCLER_VIEW_WIDGET": { "TYPE": "CLASS", "VALUE": "androidx.recyclerview.widget.RecyclerView" }, "RESET_NETWORK": { "TYPE": "TEXT", "VALUE": "Reset network" }, "RESET_SETTINGS": { "TYPE": "TEXT", "VALUE": "RESET SETTINGS" }, "RESET_APP_PREFERENCES": { "TYPE": "TEXT", "VALUE": "Reset app preferences" }, "RESET_APPS": { "TYPE": "TEXT", "VALUE": "RESET APPS" }, "LANGUAGES_MENU": { "TYPE": "TEXT", "VALUE": "Languages" }, "LANGUAGES_MENU_IN_SELECTED_LANGUAGE": { "TYPE": "TEXT", "VALUE": "Idiomas" } }, "SECURITY": { "PATH": "Settings > Security", "OPTIONS": [ ], "TITLE": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_title", "PACKAGE": "com.android.car.settings.googlecarui.rro" }, "CHOOSE_LOCK_TYPE": { "TYPE": "TEXT", "VALUE": "Choose a lock type" }, "LOCK_TYPE_PASSWORD": { "TYPE": "TEXT", "VALUE": "Password" }, "LOCK_TYPE_PIN": { "TYPE": "TEXT", "VALUE": "PIN" }, "LOCK_TYPE_NONE": { "TYPE": "TEXT", "VALUE": "None" }, "CONTINUE_BUTTON": { "TYPE": "TEXT", "VALUE": "Continue" }, "CONFIRM_BUTTON": { "TYPE": "TEXT", "VALUE": "Confirm" }, "ENTER_PASSWORD": { "TYPE": "CLASS", "VALUE": "android.widget.EditText" }, "PIN_PAD": { "TYPE": "RESOURCE_ID", "VALUE": "pin_pad", "PACKAGE": "com.android.car.settings" }, "ENTER_PIN_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "key_enter", "PACKAGE": "com.android.car.settings" }, "REMOVE_BUTTON": { "TYPE": "TEXT", "VALUE": "Remove" } } }, "PHONE": { "APPLICATION_CONFIG": { "DIAL_PACKAGE": "com.android.car.dialer", "PHONE_ACTIVITY": "com.android.car.dialer/.ui.TelecomActivity", "OPEN_DIAL_PAD_COMMAND": "am start -a android.intent.action.DIAL" }, "IN_CALL_VIEW": { "DIALED_CONTACT_TITLE": { "TYPE": "RESOURCE_ID", "VALUE": "user_profile_title", "PACKAGE": "com.android.car.dialer" }, "DIALED_CONTACT_NUMBER": { "TYPE": "RESOURCE_ID", "VALUE": "user_profile_phone_number", "PACKAGE": "com.android.car.dialer" }, "END_CALL": { "TYPE": "RESOURCE_ID", "VALUE": "end_call_button", "PACKAGE": "com.android.car.dialer" }, "MUTE_CALL": { "TYPE": "RESOURCE_ID", "VALUE": "mute_button", "PACKAGE": "com.android.car.dialer" }, "SWITCH_TO_DIAL_PAD": { "TYPE": "RESOURCE_ID", "VALUE": "toggle_dialpad_button", "PACKAGE": "com.android.car.dialer" }, "CHANGE_VOICE_CHANNEL": { "TYPE": "RESOURCE_ID", "VALUE": "voice_channel_view", "PACKAGE": "com.android.car.dialer" }, "VOICE_CHANNEL_CAR": { "TYPE": "TEXT", "VALUE": "Car speakers" }, "VOICE_CHANNEL_PHONE": { "TYPE": "TEXT", "VALUE": "Phone" } }, "DIAL_PAD_VIEW": { "DIAL_PAD_MENU": { "TYPE": "TEXT", "VALUE": "Dial Pad" }, "DIAL_PAD_FRAGMENT": { "TYPE": "RESOURCE_ID", "VALUE": "dialpad_fragment", "PACKAGE": "com.android.car.dialer" }, "DIALED_NUMBER": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.dialer" }, "MAKE_CALL": { "TYPE": "RESOURCE_ID", "VALUE": "call_button", "PACKAGE": "com.android.car.dialer" }, "DELETE_NUMBER": { "TYPE": "RESOURCE_ID", "VALUE": "delete_button", "PACKAGE": "com.android.car.dialer" } }, "CONTACTS_VIEW": { "CONTACTS_MENU": { "TYPE": "TEXT", "VALUE": "Contacts" }, "CONTACT_INFO": { "TYPE": "RESOURCE_ID", "VALUE": "call_action_id", "PACKAGE": "com.android.car.dialer" }, "CONTACT_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.dialer" }, "CONTACT_DETAIL": { "TYPE": "RESOURCE_ID", "VALUE": "show_contact_detail_id", "PACKAGE": "com.android.car.dialer" }, "ADD_CONTACT_TO_FAVORITE": { "TYPE": "RESOURCE_ID", "VALUE": "contact_details_favorite_button", "PACKAGE": "com.android.car.dialer" }, "SEARCH_CONTACT": { "TYPE": "RESOURCE_ID", "VALUE": "menu_item_search", "PACKAGE": "com.android.car.dialer" }, "CONTACT_SEARCH_BAR": { "TYPE": "RESOURCE_ID", "VALUE": "car_ui_toolbar_search_bar", "PACKAGE": "com.android.car.dialer" }, "SEARCH_RESULT": { "TYPE": "RESOURCE_ID", "VALUE": "contact_name", "PACKAGE": "com.android.car.dialer" }, "CONTACT_SETTINGS": { "TYPE": "RESOURCE_ID", "VALUE": "menu_item_setting", "PACKAGE": "com.android.car.dialer" }, "CONTACT_ORDER": { "TYPE": "TEXT", "VALUE": "Contact order" }, "SORT_BY_FIRST_NAME": { "TYPE": "TEXT", "VALUE": "First name" }, "SORT_BY_LAST_NAME": { "TYPE": "TEXT", "VALUE": "Last Name" }, "CONTACT_TYPE_WORK": { "TYPE": "TEXT", "VALUE": "Work" }, "CONTACT_TYPE_MOBILE": { "TYPE": "TEXT", "VALUE": "Mobile" }, "CONTACT_TYPE_HOME": { "TYPE": "TEXT", "VALUE": "Home" } }, "CALL_HISTORY_VIEW": { "CALL_HISTORY_MENU": { "TYPE": "TEXT", "VALUE": "Recents" }, "CALL_HISTORY_INFO": { "TYPE": "RESOURCE_ID", "VALUE": "call_action_id", "PACKAGE": "com.android.car.dialer" } }, "FAVORITES_VIEW": { "FAVORITES_MENU": { "TYPE": "TEXT", "VALUE": "Favorites" } } }, "NOTIFICATIONS": { "APPLICATION_CONFIG": { "OPEN_NOTIFICATIONS_COMMAND": "service call statusbar 1" }, "EXPANDED_NOTIFICATIONS_SCREEN": { "NOTIFICATION_VIEW": { "TYPE": "RESOURCE_ID", "VALUE": "notification_view", "PACKAGE": "com.android.systemui" }, "CLEAR_ALL_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "clear_all_button", "PACKAGE": "com.android.systemui" }, "STATUS_BAR": { "TYPE": "RESOURCE_ID", "VALUE": "car_top_navigation_bar_container", "PACKAGE": "com.android.systemui" }, "APP_ICON": { "TYPE": "RESOURCE_ID", "VALUE": "app_icon", "PACKAGE": "com.android.systemui" }, "APP_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "header_text", "PACKAGE": "com.android.systemui" }, "NOTIFICATION_TITLE": { "TYPE": "RESOURCE_ID", "VALUE": "notification_body_title", "PACKAGE": "com.android.systemui" }, "NOTIFICATION_BODY": { "TYPE": "RESOURCE_ID", "VALUE": "notification_body_content", "PACKAGE": "com.android.systemui" }, "CARD_VIEW": { "TYPE": "RESOURCE_ID", "VALUE": "card_view", "PACKAGE": "com.android.systemui" } } }, "MEDIA_CENTER": { "APPLICATION_CONFIG": { "MEDIA_CENTER_PACKAGE": "com.android.car.media", "MEDIA_ACTIVITY": "com.android.bluetooth/com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService" }, "MEDIA_CENTER_SCREEN": { "PLAY_PAUSE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "play_pause_stop", "PACKAGE": "com.android.car.media" }, "NEXT_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_next", "PACKAGE": "com.android.car.media" }, "PREVIOUS_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_prev", "PACKAGE": "com.android.car.media" }, "SHUFFLE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "overflow_on", "PACKAGE": "com.android.car.media" }, "PLAY_QUEUE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "play_queue", "PACKAGE": "com.android.car.media" }, "MINIMIZED_MEDIA_CONTROLS": { "TYPE": "RESOURCE_ID", "VALUE": "minimized_playback_controls", "PACKAGE": "com.android.car.media" }, "TRACK_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.media" }, "TRACK_NAME_MINIMIZED_CONTROL": { "TYPE": "RESOURCE_ID", "VALUE": "minimized_control_bar_title", "PACKAGE": "com.android.car.media" }, "BACK_BUTTON": { "TYPE": "DESCRIPTION", "VALUE": "Back" } }, "MEDIA_CENTER_ON_HOME_SCREEN": { "PLAY_PAUSE_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "play_pause_stop", "PACKAGE": "com.android.car.carlauncher" }, "NEXT_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_next", "PACKAGE": "com.android.car.carlauncher" }, "PREVIOUS_BUTTON": { "TYPE": "RESOURCE_ID", "VALUE": "skip_prev", "PACKAGE": "com.android.car.carlauncher" }, "TRACK_NAME": { "TYPE": "RESOURCE_ID", "VALUE": "title", "PACKAGE": "com.android.car.carlauncher" } } } }
إعدادات الجهاز البديلة
يعرض نموذج الرمز التالي مثالاً على ملف إعداد JSON يتم فيه إلغاء الإعدادات التلقائية من خلال الإعدادات على الجهاز قيد الاختبار. في هذا المثال:
يُطلق على إعدادات الإنترنت اسم الشبكة والإنترنت على الأجهزة المرجعية والاتصال على الجهاز قيد الاختبار.
تتوفّر إعدادات التاريخ والوقت في الإعدادات > التاريخ والوقت للأجهزة المرجعية وفي الإعدادات > النظام > التاريخ والوقت للجهاز قيد الاختبار.
// Default configuration file
{
....
"SECURITY_SETTINGS_SCROLL_ELEMENT": {
"TYPE": "RESOURCE_ID",
"VALUE": "fragment_container",
},
....
}
// JSON configuration file for non-reference device
{
....
"SECURITY_SETTINGS_SCROLL_ELEMENT": {
"TYPE": "RESOURCE_ID",
"VALUE": "car_ui_recycler_view"
},
....
}
عندما يصبح ملف إعداد JSON جاهزًا، يتم توفيره في وقت التشغيل كما هو موضّح في مجموعة الرموز التالية:
# Push The JSON configuration file to the device
adb -s DEVICE-SERIAL push PATH-OF-JSON-FILE /data/local/tmp/runtimeSpectatioConfig.json
وفي هذا الأمر:
DEVICE-SERIAL: رقم تعريف الجهاز قيد الاختبار التسلسلي هذه المَعلمة غير مطلوبة إذا كان جهاز واحد فقط متصلاً بالمضيف.
PATH-TO-JSON-FILE: مسار ملف JSON على الجهاز المضيف
تنسيق الإعدادات
هناك خمسة عناصر ذات مستوى أعلى في الإعدادات، مع المفاتيح والقيم التالية:
| عنصر | الوصف |
|---|---|
PACKAGES |
عنصر يصف الحزمة الرئيسية لمختلف التطبيقات، والتي تُستخدَم لتحديد متى يكون هذا التطبيق في المقدّمة |
ACTIONS |
عنصر يشير إلى أنواع الإجراءات ومَعلماتها لمختلف الإجراءات على سبيل المثال، ما إذا كان يجب استخدام الأزرار أو إيماءة للتمرير |
COMMANDS |
عنصر يحدّد الأوامر التي تنفّذ إجراءات مختلفة |
UI_ELEMENTS |
عنصر يُستخدَم لإنشاء `BySelectors` في UI Automator التي تختار عناصر واجهة المستخدم (موضّحة بالتفصيل أدناه) |
WORKFLOWS |
تسلسلات من الإجراءات التي تُنجز مهامًا عالية المستوى (موضّحة بالتفصيل أدناه) |
عناصر واجهة المستخدم
لكل عنصر في واجهة المستخدم TYPE يحدّد ما سيبحث عنه UI Automator لتحديد العنصر (مثل رقم تعريف المورد والنص والوصف) وقيم الإعدادات المرتبطة بهذا النوع. بشكل عام، كلما حدّد مساعد عنصرًا على الشاشة باستخدام هذا الإعداد، يحصل على عنصر واحد فقط. إذا تطابقت عناصر متعددة مع الإعداد، يتم استخدام عنصر عشوائي في الاختبار. لذلك، يجب (بشكل عام) كتابة الإعداد بشكل محدّد بما يكفي ليقتصر على عنصر واحد في السياق ذي الصلة.
النص
هذا هو أبسط نوع من عناصر واجهة المستخدم. يتم تحديد عنصر في واجهة المستخدم من خلال النص، ويتطلب مطابقة تامة.
"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"
}
CLICKABLE, SCROLLABLE
حدِّد العنصر استنادًا إلى ما إذا كان قابلاً للنقر أو التمرير (أو غير قابل لذلك).
هذه الأنواع من العناصر واسعة جدًا، ولا يجب استخدامها بشكل عام إلا في MULTIPLE للمساعدة في تضييق نطاق نوع عنصر آخر. المفتاح FLAG اختياري، ويتم ضبطه تلقائيًا على true.
"SAMPLE_ELEMENT": {
"TYPE": "CLICKABLE",
"FLAG": false
}
الصف
حدِّد العنصر استنادًا إلى فئته.
"SECURITY_SETTINGS_ENTER_PASSWORD": {
"TYPE": "CLASS",
"VALUE": "android.widget.EditText"
}
HAS_ANCESTOR
حدِّد العنصر من خلال البحث عن التسلسل الهرمي للقطعة في العناصر الرئيسية. يحتوي المفتاح ANCESTOR على عنصر يحدّد العنصر الرئيسي. يحدّد المفتاح DEPTH مدى البحث في التسلسل الهرمي. DEPTH اختياري وله قيمة تلقائية هي 1.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_ANCESTOR",
"DEPTH": 2,
"ANCESTOR": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
HAS_DESCENDANT
حدِّد العنصر من خلال البحث في التسلسل الهرمي عن العناصر الفرعية. يحتوي المفتاح DESCENDANT على عنصر يحدّد العنصر الفرعي الذي يجب البحث عنه. يحدّد المفتاح DEPTH مدى البحث في التسلسل الهرمي. DEPTH اختياري وله قيمة تلقائية هي 1.
"SAMPLE_ELEMENT": {
"TYPE": "HAS_DESCENDANT",
"DEPTH": 2,
"DESCENDANT": {
"TYPE": "CLASS",
"VALUE": "android.view.ViewGroup"
}
}
متعدد
حدِّد العنصر استنادًا إلى شروط متعدّدة متزامنة، يجب استيفاؤها كلها.
"APP_INFO_SETTINGS_PERMISSION_MANAGER": {
"TYPE": "MULTIPLE",
"SPECIFIERS": [
{
"TYPE": "CLASS",
"VALUE": "android.widget.RelativeLayout"
},
{
"TYPE": "HAS_DESCENDANT",
"MAX_DEPTH": 2,
"DESCENDANT": {
"TYPE": "TEXT",
"VALUE": "Permission manager"
}
}
]
}
في هذا المثال، يحدّد الإعداد RelativeLayout يحتوي على عنصر فرعي على العمق 2، والذي يحتوي على النص Permission manager.
Workflows
يمثّل سير العمل تسلسلاً من الإجراءات المستخدَمة لإنجاز مهمة معيّنة، والتي قد تختلف بشكل كافٍ من نوع جهاز إلى آخر، وتكون أكثر مرونة في تمثيلها في الإعدادات مقارنةً بالرمز.
"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 الذي تأخذ قيمته الشكل نفسه كإدخال عنصر في واجهة المستخدم (راجِع أعلاه). هذه الأنواع هي:
| 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 |
بالنسبة إلى الأنواع الأخرى، تكون تفاصيل الإعدادات كما يلي:
| عنصر | الوصف |
|---|---|
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 |
عنصر يشير إلى الحاوية التي يجب تمريرها، باستخدام الشكل نفسه كإعداد عنصر واجهة المستخدم (راجِع أعلاه) |
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 للاختبار، يجب أن تكون قاعدة الرموز البرمجية لمشروع Android المفتوح المصدر (AOSP) على محطة العمل المحلية. بعد إنشاء حزمة APK للاختبار، على المستخدم تثبيت حزمة APK على الجهاز وتنفيذ الاختبار.
تعرض عينة التعليمات البرمجية التالية عملية إنشاء حزمة APK للاختبار وتثبيتها وتنفيذها.
# Build Test APK make TEST-APK-NAME# Install Test APK adb -s DEVICE-SERIAL install -r PATH-FOR-BUILT-TEST-APK# Execute Test with the JSON file adb -s DEVICE-SERIAL shell am instrument -w -r -e debug false -e config-file-path /data/local/tmp/jsonFile.json -e class TEST-PACKAGE.TEST-CLASSNAME TEST-PACKAGE/androidx.test.runner.AndroidJUnitRunner
في هذه الأوامر:
TEST-APK-NAME: اسم التطبيق الذي سيتم اختباره على سبيل المثال، اضبط TEST-APK-NAME على
AndroidAutomotiveSettingsTestsلاختبار إعدادات Wi-Fi كما هو محدّد فيAndroid.bpملف. يمكن العثور على اسم حزمة APK في ملفAndroid.bpالمعنيّ لـ اختبار السيارات.DEVICE-SERIAL: رقم تعريف الجهاز قيد الاختبار التسلسلي هذه المَعلمة غير مطلوبة إذا كان جهاز واحد فقط متصلاً بالمضيف.
config-file-path: مَعلمة اختيارية مطلوبة فقط لتوفير إعدادات واجهة مستخدم الجهاز غير التلقائية كما هو محدّد في ملف إعداد JSON. إذا لم يتم توفيرها، يستخدم إطار العمل القيم التلقائية لتنفيذ الاختبارات.PATH-FOR-BUILT-TEST-APK: المسار الذي يتم فيه إنشاء حزمة APK للاختبار عند تنفيذ الأمر
makeTEST-PACKAGE: اسم حزمة الاختبار
TEST-CLASSNAME: اسم فئة الاختبار على سبيل المثال، لاختبار إعدادات Wi-Fi، تكون حزمة الاختبار هي
android.platform.testsواسم فئة الاختبار هوWifiSettingTest.
مكتبة مقتطفات السيارات
مكتبة مقتطفات السيارات هي مجموعة من مكتبات Android Test لمشروع Android مفتوح المصدر (AOSP) المصمّمة للتفاعل مع تطبيقات وخدمات السيارات. تستخدِم Spectatio آلية ملائمة لتنفيذ طلبات الإجراءات عن بُعد (RPC) من جهاز مضيف (جهاز الاختبار) إلى جهاز يعمل بنظام التشغيل Android.
البدء
قبل البدء، راجِع هذه الأقسام.
المتطلبات الأساسية
- تثبيت الإصدار 3.x من Python على الجهاز المضيف
- إعداد بيئة AOSP باستخدام أدوات الإنشاء اللازمة
- جهاز سيارة يعمل بنظام التشغيل Android (محاكي أو جهاز فعلي) مع إمكانية الوصول إلى adb
موسيقى مجمّعة
لتجميع المقتطفات المختلفة التي توفّرها مكتبة مقتطفات السيارات، يمكنك استخدام ملف android.bp المقدَّم. اتّبِع الأوامر الواردة في القسم السابق لتجميع حزمة APK.
التفعيل
بعد تجميع مكتبات المقتطفات بنجاح، يمكنك نشر حِزم APK الناتجة على جهاز الاختبار باستخدام الأمر adb install المذكور في القسم السابق.
إجراء الاختبارات
تعرض مكتبات المقتطفات عدة طرق لطلبات الإجراءات عن بُعد للتفاعل مع نظام السيارات. يمكن استدعاء هذه الطرق من خلال إطار عمل Mobly من الجهاز المضيف. بافتراض أنّك أعددت بيئة اختبار Mobly، يمكنك استخدام الـ
snippet_shell.py لفتح واجهة تفاعلية في Python، حيث يمكنك
استدعاء طرق طلبات الإجراءات عن بُعد يدويًا على الجهاز. مثال على الاستدعاء:
python3 snippet_shell.py com.google.android.mobly.snippet.bundled -s <serial>
استبدِل <serial> بالرقم التسلسلي للجهاز، الذي يمكنك الحصول عليه باستخدام
adb devices إذا كانت أجهزة متعددة متصلة.
المكتبات المضمّنة
تتضمّن مكتبة مقتطفات السيارات مكتبات وأدوات مساعدة المقتطفات التالية:
AutomotiveSnippet: توفّر واجهات برمجة تطبيقات ذات صلة بعمليات السيارة، مثل الاتصال والتحكّم في مستوى الصوت والمفاتيح الثابتة في السيارة والتفاعل مع مركز الوسائط
PhoneSnippet: توفّر واجهات برمجة تطبيقات ذات صلة بالاتصالات الهاتفية، بما في ذلك معالجة المكالمات وتصفّح جهات الاتصال وعمليات الرسائل القصيرة SMS
يتشارك مقتطف السيارات وPhoneSnippet بعض المنطق الشائع.
على وجه التحديد، يمكنك إرسال طلبات الإجراءات عن بُعد ذات الصلة بتقنية البلوتوث لإقران جهاز سيارة وجهاز هاتف. يوضّح هذا bt_discovery_test كيفية إجراء ذلك.
- TEST-CLASSNAME: اسم فئة الاختبار على سبيل المثال، لاختبار
إعدادات Wi-Fi،
تكون حزمة الاختبار هي
android.platform.testsواسم فئة الاختبار هوWifiSettingTest.