Spectatio هو إطار عمل اختباري مفتوح المصدر تم تطويره لاختبار نظام التشغيل Android Automotive (AAOS) على الأجهزة الحقيقية والافتراضية. توفّر Spectatio واجهات برمجة تطبيقات لاختبار التطبيقات على جهاز سيارة، وهي حلّ قابل للتوسيع والتطوير ويُستخدَم للتحقّق من قدرة نظام التشغيل AAOS وتطبيقاته وأداءها.
التصميم العالي المستوى
إطار عمل Spectatio قابل للتكيّف والتوسيع لتنفيذات مختلفة لواجهة مستخدم AAOS. ويُستخدَم لاختبار قدرات نظام التشغيل AAOS على أجهزة الأجهزة والمحاكيات والبيئات الافتراضية.
يوضّح الشكل التالي التصميم العام لإطار عمل Spectatio.
الشكل 1: تصميم عالي المستوى لإطار عمل Spectatio
يستند إطار عمل Spectatio إلى UI Automator، ويقدّم مجموعة من واجهات برمجة التطبيقات لإنشاء اختبارات واجهة المستخدم التي تتفاعل مع تطبيقات المستخدم والنظام على نظام التشغيل AAOS. تستخدم اختبارات السيارات واجهات برمجة التطبيقات التي يوفّرها إطار عمل Spectatio للاختبار، ما يجعل هذه الاختبارات مستقلة عن الجهاز قيد الاختبار (DUT) وقابلة للتطوير لاختبار الأجهزة المتنوعة، إذا كان ذلك متاحًا.
يوضّح الشكل 1 أنّ إطار عمل Spectatio ينقسم إلى وحدات استنادًا إلى تطبيقات مرجعية، مثل Dialer وMedicenter و"الإعدادات" باستخدام واجهات وأدوات مساعدة خاصة بالتطبيقات، ما يجعله قابلاً للتوسّع بسهولة للتطبيقات الجديدة. يعيد إطار عمل 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: المعرّف التسلسلي لـ DUT هذه المَعلمة ليست مطلوبة إذا كان هناك جهاز واحد فقط متصل بالمضيف.
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
تأخذ قيمته
الشكل نفسه لقيمة إدخال عنصر واجهة المستخدم (راجِع أعلاه). هذه TYPE هي:
الضغط الضغط مع الاستمرار النقر النقر مع الاستمرار النقر إذا كان متوفّرًا |
HAS_UI_ELEMENT_IN_FOREGROUND SCROLL_TO_FIND_AND_CLICK SCROLL_TO_FIND_AND_CLICK_IF_EXIST SWIPE_TO_FIND_AND_CLICK SWIPE_TO_FIND_AND_CLICK_IF_EXIST |
بالنسبة إلى القيم الأخرى لـ TYPE، تكون تفاصيل الضبط كما يلي:
عنصر | الوصف |
---|---|
COMMAND |
عنصر يحمل قيمة TEXT يحتوي على الأمر المطلوب تنفيذه |
HAS_PACKAGE_IN_FOREGROUND |
كائن ذو القيمة TEXT يحتوي على الحزمة. |
SWIPE |
إزالة الرمز 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
المعنيّ لإجراء اختبار السيارات.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.
البدء
قبل البدء، راجِع هذه الأقسام.
المتطلّبات الأساسية
- تثبيت Python 3.x على الجهاز المضيف.
- إعداد بيئة AOSP باستخدام أدوات الإنشاء اللازمة
- جهاز Android للسيارات (المحاكي أو الجهاز الفعلي) مع إمكانية الوصول إلى 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 إذا كانت هناك أجهزة متعددة متصلة.
المكتبات المضمّنة
تتضمن مكتبة مقتطفات Automotive مكتبات المقتطفات والعناصر التالية المساعدة:
AutomotiveSnippet: يوفّر واجهات برمجة تطبيقات ذات صلة بعمليات المركبات، مثل طلب الاتصال والتحكّم في مستوى الصوت والمفاتيح الثابتة للمركبة والتفاعل مع مركز الوسائط.
Phonesnippet: توفر واجهات برمجة التطبيقات المتعلقة بالاتصالات الهاتفية، بما في ذلك التعامل مع المكالمات، وتصفح جهات الاتصال، وعمليات الرسائل القصيرة SMS.
يتشارك AutomotiveSnippet وPhoneSnippet بعض المنطق الشائع.
على وجه التحديد، يمكنك اختراق طلبات RCP ذات الصلة بالبلوتوث لإقران جهاز مركبة
بجهاز هاتف. يوضّح لك هذا bt_discovery_test
كيفية إجراء ذلك.
- TEST-CLASSNAME: اسم فئة الاختبار. على سبيل المثال، بالنسبة إلى اختبار
إعدادات Wi-Fi،
تكون حزمة الاختبار هي
android.platform.tests
واسم فئة الاختبار هوWifiSettingTest
.