Spectatio هو إطار عمل اختبار مفتوح المصدر تم تطويره لاختبار نظام التشغيل Android Automotive (AAOS) على الأجهزة الفعلية والافتراضية. توفّر Spectatio واجهات برمجة تطبيقات لاختبار التطبيقات على جهاز سيارة، وهي حلّ قابل للتوسيع والتطوير ويُستخدَم للتحقّق من قدرة نظام التشغيل AAOS وتطبيقاته وأداءها.
التصميم العالي المستوى
إطار عمل Spectatio قابل للتكيّف والتوسيع لتنفيذات مختلفة لواجهة مستخدم AAOS. ويُستخدَم لاختبار قدرات نظام التشغيل AAOS وأداءه على أجهزة الأجهزة والمحاكيات والبيئات الافتراضية.
يوضّح الشكل التالي التصميم العام لإطار عمل Spectatio.
الشكل 1: تصميم عالي المستوى لإطار عمل Spectatio
يستند إطار عمل Spectatio إلى UI Automator، ويقدّم مجموعة من واجهات برمجة التطبيقات لإنشاء اختبارات واجهة المستخدم التي تتفاعل مع تطبيقات المستخدم والنظام على نظام التشغيل AAOS. تستخدِم اختباراتยานยนต์ واجهات برمجة التطبيقات التي يوفّرها إطار عمل Spectatio للاختبار، ما يجعل هذه الاختبارات مستقلة عن الجهاز الذي يتم اختباره (DUT) وقابلة للتوسّع لاختبار الأجهزة المختلفة، إذا كان ذلك متوافقًا.
يوضّح الشكل 1 أنّ إطار عمل Spectatio مصنّف إلى وحدات استنادًا إلى التطبيقات المرجعية مثل Dialer وMedicenter وSettings باستخدام واجهات ومقاييس مساعدة خاصة بالتطبيق، ما يسهّل توسيع نطاقه ليشمل التطبيقات الجديدة. يعيد إطار عمل Spectatio استخدام فئات المساعدة الشائعة والمرافق. فئة المساعدة العادية: هي الفئة الرئيسية لجميع وظائف مساعدة التطبيقات، وتقدّم وظائف عادية خاصة بالجهاز أو قابلة للتطبيق على جميع التطبيقات. توفّر فئات مساعدة الأداة أدوات مثل قراءة الملفات أو كتابتها من الجهاز.
هندسة معمارية
لتوفير مجموعة من واجهات برمجة التطبيقات لإنشاء اختبارات واجهة المستخدم، ينفِّذ إطار عمل Spectatio واجهات ومساعِدين خاصّين بالتطبيق مع توسيع نطاق فئة المساعِد العادية الحالية واستيراد فئات المساعِدين في الأداة.
يوضّح الشكل 2 البنية الأساسية العالية المستوى لإطار عمل Spectatio وجميع الكيانات المشارِكة في تنفيذ واجهات برمجة التطبيقات لاختبار أحد التطبيقات.
الشكل 2: بنية Spectatio الإطارية العالية المستوى
توفّر واجهة "مساعِد التطبيق" مخطّط عمل لتنفيذ
مساعِد التطبيق. ويتألف من دوال مساعدة مختلفة مطلوبة
لاختبار التطبيقات. ولكل تطبيق واجهته الخاصة، مثل IAutoSettingHelper
وIAutoDialHelper
.
لمزيد من المعلومات وقائمة بوظائف الواجهة، يُرجى الاطّلاع على وظائف واجهة مساعد التطبيق في AOSP.
تتألف فئة المساعدة العادية من سمات ودوال عادية
مطلوبة لإعداد الجهاز ولكنها ليست خاصة بأي تطبيق، مثل pressHome
وscroll
. يتم تحديد فئة المساعِد العادية في AbstractAutoStandardAppHelper.java
.
يستخدم الإطار فئات مساعدة الأداة. على سبيل المثال، AutoJsonUtility.java
هي
فئة أداة تحمّل ملف إعدادات JSON للجهاز المحدّد وتُعدِّل
إعدادات إطار العمل أثناء التشغيل.
تشكّل وحدة تنفيذ مساعدة التطبيق جوهر إطار عمل Spectatio. يحتوي على تنفيذ وظائف المساعِد المحدّدة في
واجهة مساعِد التطبيق، وهي مطلوبة لاختبار التطبيقات على
جهاز Automotive. ولكل تطبيق طريقة تنفيذ خاصة به، مثل SettingHelperImpl
و
DialHelperImpl
،
التي تستخدمها
اختبارات Automotive لاختبار التطبيقات. لمزيد من المعلومات وقائمة بالعمليات التي تم تنفيذها، يُرجى الاطّلاع على وظائف تنفيذ تطبيقات المساعِد
على 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 الذي يتم فيه إلغاء الإعدادات التلقائية من خلال الإعدادات على جهاز 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: رقم التعريف التسلسلي لوحدة التحكّم بالتجربة هذه المَعلمة ليست مطلوبة إذا كان هناك جهاز واحد فقط متصل بالمضيف.
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"
}
قابل للنقر والتمرير
حدِّد العنصر استنادًا إلى ما إذا كان قابلاً للنقر (أو لا) أو قابلاً للانتقال للأعلى أو للأسفل.
هذه أنواع عناصر واسعة جدًا، ويجب عدم استخدامها بشكل عام إلا في ملف تعريف
MULTIPLE
للمساعدة في تضييق نطاق نوع عنصر آخر. مفتاح FLAG
اختياري، ويُضبط تلقائيًا على true
.
"SAMPLE_ELEMENT": {
"TYPE": "CLICKABLE",
"FLAG": false
}
CLASS
حدِّد العنصر استنادًا إلى فئته.
"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"
}
}
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"
}
}
]
}
في هذا المثال، تحدِّد الإعدادات 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
(في بعض الأحيان). بالنسبة إلى
معظم الأنواع، يكون CONFIG
عنصرًا يحتوي على مفتاح UI_ELEMENT
تأخذ قيمته
الشكل نفسه لقيمة إدخال عنصر واجهة المستخدم (راجِع أعلاه). وتشمل هذه الأنواع ما يلي:
الضغط الضغط مع الاستمرار النقر النقر مع الاستمرار النقر إذا كان متوفّرًا |
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 الاختبارية، يجب أن تكون قاعدة بيانات 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: رقم التعريف التسلسلي لوحدة التحكّم بالتجربة لا يُشترط استخدام هذه المَعلمة إذا كان هناك جهاز واحد فقط متصل بالمضيف.
config-file-path
: مَعلمة اختيارية مطلوبة فقط لتوفير إعدادات واجهة مستخدم الجهاز غير التلقائية كما هو محدّد في ملف إعدادات JSON. في حال عدم تقديمها، يستخدم الإطار القيم التلقائية لتنفيذ الاختبارات.PATH-FOR-BUILT-TEST-APK: المسار الذي يتم فيه إنشاء حزمة APK الاختبارية عند تنفيذ الأمر
make
TEST-PACKAGE: اسم حزمة الاختبار
TEST-CLASSNAME: اسم فئة الاختبار. على سبيل المثال، بالنسبة إلى اختبار إعدادات Wi-Fi، تكون حزمة الاختبار هي
android.platform.tests
واسم صف الاختبار هوWifiSettingTest
.
مكتبة المقتطفات المتعلّقة بالسيارات
مكتبة مقتطفات Automotive هي مجموعة من مكتبات اختبار Android لمشروع Android المفتوح المصدر (AOSP) المصمّمة للتفاعل مع التطبيقات والخدمات المتعلّقة بالسيارات. ويستفيد Spectatio من آلية مناسبة لتنفيذ طلبات الإجراءات عن بُعد (RPC) من جهاز مضيف (اختباري) إلى جهاز Android.
البدء
قبل البدء، راجِع هذه الأقسام.
المتطلّبات الأساسية
- تثبيت الإصدار 3.x من لغة Python على الجهاز المضيف
- إعداد بيئة AOSP باستخدام أدوات الإنشاء اللازمة
- جهاز Android Automotive (محاكي أو جهاز فعلي) يتيح الوصول إلى adb
موسيقى مجمّعة
لتجميع المقتطفات المختلفة التي تقدّمها "مكتبة المقتطفات المتعلّقة بالسيارات"،
يمكنك استخدام ملف android.bp
المقدَّم. اتّباع الأوامر الواردة في القسم السابق
لإنشاء حزمة APK
التفعيل
بعد تجميع مكتبات المقتطفات بنجاح، يمكنك نشر حِزم APK الناتجة على
الجهاز المستهدَف باستخدام الأمر adb install
المذكور في القسم السابق.
إجراء الاختبارات
تعرض مكتبات المقتطفات العديد من طرق RPC للتفاعل مع نظام المركبات. يمكن استدعاء هذه الطرق من خلال إطار عمل Mobly من المضيف
الجهاز. بافتراض أنّك قد أعددت بيئة اختبار Mobly، يمكنك استخدام النص البرمجي
snippet_shell.py
لفتح بيئة Python تفاعلية، حيث يمكنك
استدعاء طرق RPC يدويًا على الجهاز. مثال على طلب التنفيذ:
python3 snippet_shell.py com.google.android.mobly.snippet.bundled -s <serial>
استبدِل <serial>
بالرقم التسلسلي للجهاز، والذي يمكنك الحصول عليه باستخدام ملفadb devices إذا كانت هناك أجهزة متعددة متصلة.
المكتبات المضمّنة
تتضمّن مكتبة المقتطفات المتعلّقة بالسيارات مكتبات المقتطفات التالية ومقتطفات المساعدة التالية:
AutomotiveSnippet: يوفّر واجهات برمجة تطبيقات ذات صلة بعمليات المركبات، مثل طلب الاتصال والتحكّم في مستوى الصوت والمفاتيح الثابتة للمركبة والتفاعل مع مركز الوسائط.
PhoneSnippet: يوفّر واجهات برمجة تطبيقات متعلّقة بخدمات الهاتف، بما في ذلك معالجة المكالمات، والتصفّح في جهات الاتصال، وعمليات الرسائل القصيرة.
يتشارك AutomotiveSnippet وPhoneSnippet بعض المنطق الشائع.
على وجه التحديد، يمكنك اختراق طلبات RCP ذات الصلة بالبلوتوث لإقران جهاز مركبة
بجهاز هاتف. يوضّح لك هذا bt_discovery_test
كيفية إجراء ذلك.
- TEST-CLASSNAME: اسم فئة الاختبار. على سبيل المثال، بالنسبة إلى اختبار
إعدادات Wi-Fi،
تكون حزمة الاختبار هي
android.platform.tests
واسم فئة الاختبار هوWifiSettingTest
.