Spectatio: إطار اختبار السيارات

Spectatio هو إطار اختبار مفتوح المصدر تم تطويره لاختبار نظام التشغيل Android Automotive OS (AAOS) على الأجهزة الحقيقية والافتراضية. يوفر Spectatio واجهات برمجة التطبيقات (APIs) لاختبار التطبيقات على جهاز السيارة وهو حل قابل للتوسيع والتوسع يستخدم للتحقق من قدرة وأداء AAOS وتطبيقاته.

تصميم عالي المستوى

إطار عمل Spectatio قابل للتكيف والتوسيع لمختلف تطبيقات AAOS UI. يتم استخدامه لاختبار قدرة وأداء AAOS على أجهزة الجهاز والمحاكيات والبيئات الافتراضية.

يشرح الشكل التالي التصميم عالي المستوى لإطار عمل Spectatio.

إطار Spectatio تصميم رفيع المستوى

الشكل 1. تصميم إطار Spectatio رفيع المستوى.

يوفر إطار عمل Spectatio المبني على UI Automator مجموعة من واجهات برمجة التطبيقات لإنشاء اختبارات واجهة المستخدم التي تتفاعل مع تطبيقات المستخدم والنظام على AAOS. تستخدم اختبارات السيارات واجهات برمجة التطبيقات التي يوفرها إطار عمل Spectatio للاختبار، مما يجعل هذه الاختبارات مستقلة عن الجهاز قيد الاختبار (DUT) وقابلة للتطوير لاختبار الأجهزة المتنوعة، إذا كانت مدعومة.

يوضح الشكل 1 أن إطار عمل Spectatio نموذجي استنادًا إلى التطبيقات المرجعية مثل Dialer وMedicenter والإعدادات باستخدام واجهات ومساعدات خاصة بالتطبيق، مما يجعله قابلاً للتوسيع بسهولة للتطبيقات الجديدة. يعيد إطار عمل Spectatio استخدام الفئات المساعدة القياسية والأدوات المساعدة الشائعة. فئة المساعد القياسية هي الفئة الأصلية لجميع وظائف مساعد التطبيق وتوفر وظائف قياسية خاصة بالجهاز أو قابلة للتطبيق عبر التطبيقات. توفر فئات المساعدة المساعدة أدوات مساعدة مثل قراءة الملفات أو كتابتها من الجهاز.

بنيان

لتوفير مجموعة من واجهات برمجة التطبيقات لبناء اختبارات واجهة المستخدم، يقوم إطار عمل Spectatio بتنفيذ واجهات ومساعدات خاصة بالتطبيق مع توسيع فئة المساعد القياسية الحالية واستيراد فئات مساعد الأداة المساعدة.

يوضح الشكل 2 البنية عالية المستوى لإطار عمل Spectatio وجميع الكيانات المشاركة في تنفيذ واجهات برمجة التطبيقات لاختبار التطبيق.

إطار 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 application
    autoApplicationHelper.open();
  }

  @After
  public void afterTest() {
    // Cleanup after each test.
    // For example - exit the application
    autoApplicationHelper.exit();
  }

  @Test
  public void testApplicationFeature() {
    // Test
    // For example - Test if application is open
    assertTrue("Application is not open.", autoApplicationHelper.isOpen());
  }
}

التخصيص

يعد إطار عمل Spectatio مستقلاً عن واجهة مستخدم الجهاز، لذا فهو قابل للتطوير لاختبار الأجهزة ذات واجهات المستخدم والأجهزة المتنوعة. ولتحقيق قابلية التوسع هذه، يستخدم Spectatio تكوينات الجهاز الافتراضية بناءً على الجهاز المرجعي. لدعم تكوينات الأجهزة غير الافتراضية، يستخدم إطار العمل ملف تكوين JSON في وقت التشغيل لتعيين تغييرات واجهة المستخدم المطلوبة للجهاز. يدعم ملف تكوين JSON عناصر واجهة المستخدم مثل TEXT و DESCRIPTION و RESOURCE_ID ، بالإضافة إلى إعدادات path ويجب أن يحتوي فقط على معلومات حول تغييرات واجهة المستخدم لـ DUT. تستخدم بقية عناصر واجهة المستخدم قيم التكوين الافتراضية المتوفرة في إطار العمل.

تكوينات الجهاز الافتراضية

يعرض نموذج ملف تكوين 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 كائن يستخدم لإنشاء UI Automator `BySelectors` الذي يحدد عناصر واجهة المستخدم (الموصوفة بالتفصيل أدناه).
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
    }

فصل

تحديد العنصر على أساس فئته.

    "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": {
    "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 . بالنسبة لمعظم أنواع TYPEs، يكون CONFIG كائنًا يحتوي على مفتاح UI_ELEMENT الذي تأخذ قيمته نفس شكل إدخال عنصر واجهة المستخدم (انظر أعلاه). تلك الأنواع هي:

يضعط
ضغطة طويلة
انقر
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

واحدة من التالية:

  • FULL : قم بتمرير الإيماءة من حافة الشاشة إلى حافة الشاشة

    أو،
  • DEFAULT : حافة الشاشة إلى حافة الشاشة، مع وجود مخزن مؤقت بخمسة (5) بكسل على كل جانب.

    أو،
  • THREE_QUARTER أو HALF أو QUARTER : تنتهي إيماءة السحب بخمسة (5) بكسل من حافة الشاشة، وتبدأ عند النقطة التي تغطي المسافة المحددة من الشاشة.
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 : المعرف التسلسلي لـ DUT. هذه المعلمة غير مطلوبة إذا كان هناك جهاز واحد فقط متصل بالمضيف.

  • config-file-path : معلمة اختيارية مطلوبة فقط لتوفير تكوينات غير افتراضية لواجهة مستخدم الجهاز كما هو محدد في ملف تكوين JSON . إذا لم يتم توفيره، يستخدم إطار العمل القيم الافتراضية لتنفيذ الاختبارات.

  • PATH-FOR-BUILT-TEST-APK : المسار الذي يتم فيه إنشاء APK الاختباري عند تنفيذ أمر make .

  • TEST-PACKAGE : اسم حزمة الاختبار.

  • TEST-CLASSNAME : اسم فئة الاختبار. على سبيل المثال، بالنسبة لاختبار إعدادات Wifi ، تكون حزمة الاختبار هي android.platform.tests واسم فئة الاختبار هو WifiSettingTest .

مكتبة مقتطفات السيارات

مكتبة مقتطفات السيارات عبارة عن مجموعة من مكتبات اختبار Android لمشروع Android مفتوح المصدر (AOSP) المصممة للتفاعل مع تطبيقات وخدمات السيارات. إنه يعزز Spectatio بآلية ملائمة لتنفيذ استدعاءات الإجراءات عن بعد (RPCs) من جهاز مضيف (اختبار) إلى جهاز يعمل بنظام 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 في حالة توصيل أجهزة متعددة.

المكتبات المتضمنة

تتضمن مكتبة مقتطفات السيارات مكتبات المقتطفات والمساعدات التالية:

  • AutomotiveSnippet: يوفر واجهات برمجة التطبيقات المتعلقة بعمليات السيارة، مثل الاتصال والتحكم في مستوى الصوت والمفاتيح الصلبة للمركبة وتفاعل مركز الوسائط.

  • PhoneSnippet: يوفر واجهات برمجة التطبيقات المتعلقة بالهاتف، بما في ذلك التعامل مع المكالمات وتصفح جهات الاتصال وعمليات الرسائل النصية القصيرة.

يشترك مقتطف السيارات وPhoneSnippet في بعض المنطق المشترك. على وجه التحديد، يمكنك اختراق مكالمات RCP المتعلقة بالبلوتوث لإقران سيارة وجهاز هاتف. يوضح bt_discovery_test كيف.