Spectatio: Automotive 테스트 프레임워크

Spectatio는 실제 기기와 가상 기기에서 Android Automotive OS(AAOS)를 테스트하려고 개발된 오픈소스 테스트 프레임워크입니다. Spectatio는 자동차 기기에서 앱을 테스트하는 API를 제공하며 AAOS 및 앱의 기능과 성능을 확인하는 데 사용되는 확장 가능한 솔루션입니다.

대략적인 구성

Spectatio 프레임워크는 다양한 AAOS UI 구현에 맞게 조정 가능하고 확장 가능합니다. 기기 하드웨어와 에뮬레이터, 가상화된 환경에서 AAOS의 기능과 성능을 테스트하는 데 사용됩니다.

다음 그림은 Spectatio 프레임워크의 대략적인 구성을 설명합니다.

Spectatio 프레임워크의 대략적인 구성

그림 1. Spectatio 프레임워크의 대략적인 구성

UI Automator에 기반하여 빌드된 Spectatio 프레임워크는 AAOS에서 사용자 및 시스템 앱과 상호작용하는 UI 테스트를 빌드하는 API 모음을 제공합니다. Automotive 테스트는 Spectatio 프레임워크에서 제공하는 API를 사용하여 실행되므로 테스트 대상 기기 (DUT)와는 별개이며 지원되는 경우 다양한 기기를 테스트하도록 확장 가능합니다.

그림 1은 Spectatio 프레임워크가 앱별 인터페이스와 도우미를 사용하여 다이얼러, Medicenter, 설정과 같은 참조 앱을 바탕으로 모듈화되므로 새 앱에 맞도록 쉽게 확장 가능함을 보여줍니다. Spectatio 프레임워크는 공통 표준 및 유틸리티 도우미 클래스를 재사용합니다. 표준 도우미 클래스는 모든 앱 도우미 함수의 상위 클래스이며 기기별 또는 앱 전반에 사용할 수 있는 표준 함수를 제공합니다. 유틸리티 도우미 클래스는 기기에서 파일 읽기 또는 쓰기와 같은 유틸리티를 제공합니다.

아키텍처

UI 테스트를 빌드하는 API 모음을 제공하기 위해 Spectatio 프레임워크는 앱별 인터페이스 및 도우미를 구현하면서 기존 표준 도우미 클래스를 확장하고 유틸리티 도우미 클래스를 가져옵니다.

그림 2는 Spectatio 프레임워크의 대략적인 아키텍처와 앱 테스트를 위한 API 구현과 관련된 모든 항목을 보여줍니다.

Spectatio 프레임워크의 대략적인 아키텍처

그림 2. Spectatio 프레임워크의 대략적인 아키텍처

앱 도우미 인터페이스는 앱 도우미 구현을 위한 청사진을 제공하며 앱 테스트에 필요한 다양한 도우미 함수로 구성됩니다. 각 앱에는 IAutoSettingHelperIAutoDialHelper와 같은 자체 인터페이스가 있습니다. 자세한 내용과 인터페이스 함수 목록은 AOSP의 앱 도우미 인터페이스 함수를 참고하세요.

표준 도우미 클래스는 기기 설정에 필요하지만 앱과는 관련이 없는 표준 속성과 함수로 구성됩니다(예: pressHome, scroll). 표준 도우미 클래스는 AbstractAutoStandardAppHelper.java에 정의되어 있습니다.

유틸리티 도우미 클래스는 Spectatio 프레임워크에 의해 사용됩니다. 예를 들어 AutoJsonUtility.java는 지정된 기기 JSON 구성 파일을 로드하고 런타임 시 프레임워크 구성을 업데이트하는 유틸리티 클래스입니다.

앱 도우미 구현 모듈은 Spectatio 프레임워크의 핵심입니다. 여기에는 앱 도우미 인터페이스에 정의되어 있으며 자동차 기기에서 앱을 테스트하는 데 필요한 도우미 함수 구현이 포함됩니다. 각 앱에는 SettingHelperImplDialHelperImpl과 같은 자체 구현이 있고 이는 Automotive의 앱 테스트에서 사용됩니다. 자세한 내용과 구현 목록은 AOSP의 앱 도우미 구현 함수를 참고하세요.

자동차 테스트는 앱 도우미 구현 함수를 사용하여 앱과 관련된 다양한 작업을 테스트합니다. HelperAccessor 클래스를 사용하면 앱 도우미 구현 함수에 액세스할 수 있습니다.

다음 코드는 샘플 Automotive 테스트의 설정, 정리, 실행을 보여줍니다.

@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 프레임워크는 기기 UI와는 별개이므로 다양한 UI와 하드웨어를 사용하는 기기 테스트를 위해 확장 가능합니다. Spectatio에서는 확장성을 실현하기 위해 참조 기기에 기반한 기본 기기 설정을 사용하고 기본이 아닌 기기 설정을 지원하기 위해 런타임 시 JSON 구성 파일을 사용해 원하는 UI 변경사항을 기기에 설정합니다. JSON 구성 파일은 TEXT, DESCRIPTION, RESOURCE_ID와 같은 UI 요소와 path 설정을 지원하며 DUT의 UI 변경사항에 관한 정보만 포함해야 합니다. 나머지 UI 요소는 프레임워크에 제공된 기본 구성 값을 사용합니다.

기본 기기 설정

다음 샘플 JSON 구성 파일은 사용 가능한 기기 설정 및 기본값을 보여줍니다.

샘플 JSON 구성 파일을 표시하려면 여기를 클릭하세요.

    {
        "SETTINGS": {
                "APPLICATION_CONFIG": {
                        "SETTINGS_TITLE_TEXT": "Settings",
                        "SETTINGS_PACKAGE": "com.android.car.settings",
                        "SETTINGS_RRO_PACKAGE": "com.android.car.settings.googlecarui.rro",
                        "OPEN_SETTINGS_COMMAND": "am start -a android.settings.SETTINGS",
                        "OPEN_QUICK_SETTINGS_COMMAND": "am start -n com.android.car.settings/com.android.car.settings.common.CarSettingActivity"
                },
                "QUICK_SETTINGS": {
                        "OPEN_MORE_SETTINGS": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "toolbar_menu_item_1",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "NIGHT_MODE": {
                                "TYPE": "TEXT",
                                "VALUE": "Night mode"
                        }
                },
                "DISPLAY": {
                        "PATH": "Settings > Display",
                        "OPTIONS": [
                                "Brightness level"
                        ],
                        "BRIGHTNESS_LEVEL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "seekbar",
                                "PACKAGE": "com.android.car.settings"
                        }
                },
                "SOUND": {
                        "PATH": "Settings > Sound",
                        "OPTIONS": [
                                "Media volume",
                                "Alarm volume"
                        ]
                },
                "NETWORK_AND_INTERNET": {
                        "PATH": "Settings > Network & internet",
                        "OPTIONS": [
                        ],
                        "TOGGLE_WIFI": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "master_switch",
                                "PACKAGE": "com.android.car.settings"
                        }
                },
                "BLUETOOTH": {
                        "PATH": "Settings > Bluetooth",
                        "OPTIONS": [
                        ],
                        "TOGGLE_BLUETOOTH": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_menu_item_switch",
                                "PACKAGE": "com.android.car.settings"
                        }
                },
                "APPS_AND_NOTIFICATIONS": {
                        "PATH": "Settings > Apps & notifications",
                        "OPTIONS": [
                        ],
                        "SHOW_ALL_APPS": {
                                "TYPE": "TEXT",
                                "VALUE": "Show all apps"
                        },
                        "ENABLE_DISABLE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_menu_item_text",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "DISABLE_BUTTON_TEXT": {
                                "TYPE": "TEXT",
                                "VALUE": "Disable"
                        },
                        "ENABLE_BUTTON_TEXT": {
                                "TYPE": "TEXT",
                                "VALUE": "Enable"
                        },
                        "DISABLE_APP_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "DISABLE APP"
                        },
                        "FORCE_STOP_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Force stop"
                        },
                        "OK_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "OK"
                        },
                        "PERMISSIONS_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Permissions"
                        },
                        "ALLOW_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Allow"
                        },
                        "DENY_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Deny"
                        },
                        "DENY_ANYWAY_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Deny anyway"
                        }
                },
                "DATE_AND_TIME": {
                        "PATH": "Settings > Date & time",
                        "OPTIONS": [
                                "Automatic date & time",
                "Automatic time zone"
                        ],
                        "AUTOMATIC_DATE_AND_TIME": {
                                "TYPE": "TEXT",
                                "VALUE": "Automatic date & time"
                        },
                        "AUTOMATIC_TIME_ZONE": {
                                "TYPE": "TEXT",
                                "VALUE": "Automatic time zone"
                        },
                        "SET_DATE": {
                                "TYPE": "TEXT",
                                "VALUE": "Set date"
                        },
                        "SET_TIME": {
                                "TYPE": "TEXT",
                                "VALUE": "Set time"
                        },
                        "SELECT_TIME_ZONE": {
                                "TYPE": "TEXT",
                                "VALUE": "Select time zone"
                        },
                        "USE_24_HOUR_FORMAT": {
                                "TYPE": "TEXT",
                                "VALUE": "Use 24-hour format"
                        },
                        "OK_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "toolbar_menu_item_0",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "NUMBER_PICKER_WIDGET": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.NumberPicker"
                        },
                        "EDIT_TEXT_WIDGET": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        }
                },
                "USERS": {
                        "PATH": "Settings > Users",
                        "OPTIONS": [
                                "Guest"
                        ]
                },
                "ACCOUNTS": {
                        "PATH": "Settings > Accounts",
                        "OPTIONS": [
                                "Automatically sync data"
                        ],
                        "ADD_ACCOUNT": {
                                "TYPE": "TEXT",
                                "VALUE": "ADD ACCOUNT"
                        },
                        "ADD_GOOGLE_ACCOUNT": {
                                "TYPE": "TEXT",
                                "VALUE": "Google"
                        },
                        "SIGN_IN_ON_CAR_SCREEN": {
                                "TYPE": "TEXT",
                                "VALUE": "Sign in on car screen"
                        },
                        "GOOGLE_SIGN_IN_SCREEN": {
                                "TYPE": "TEXT",
                                "VALUE": "Sign in to your Google Account"
                        },
                        "ENTER_EMAIL": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        },
                        "ENTER_PASSWORD": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        },
                        "NEXT_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Next"
                        },
                        "DONE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Done"
                        },
                        "REMOVE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Remove"
                        },
                        "REMOVE_ACCOUNT_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Remove Account"
                        }
                },
                "SYSTEM": {
                        "PATH": "Settings > System",
                        "OPTIONS": [
                                "About", "Legal information"
                        ],
                        "ABOUT_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "About"
                        },
                        "RESET_OPTIONS_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Reset options"
                        },
                        "LANGUAGES_AND_INPUT_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Languages & input"
                        },
                        "DEVICE_MODEL": {
                                "TYPE": "TEXT",
                                "VALUE": "Model"
                        },
                        "ANDROID_VERSION": {
                                "TYPE": "TEXT",
                                "VALUE": "Android version"
                        },
                        "ANDROID_SECURITY_PATCH_LEVEL": {
                                "TYPE": "TEXT",
                                "VALUE": "Android security patch level"
                        },
                        "KERNEL_VERSION": {
                                "TYPE": "TEXT",
                                "VALUE": "Kernel version"
                        },
                        "BUILD_NUMBER": {
                                "TYPE": "TEXT",
                                "VALUE": "Build number"
                        },
                        "RECYCLER_VIEW_WIDGET": {
                                "TYPE": "CLASS",
                                "VALUE": "androidx.recyclerview.widget.RecyclerView"
                        },
                        "RESET_NETWORK": {
                                "TYPE": "TEXT",
                                "VALUE": "Reset network"
                        },
                        "RESET_SETTINGS": {
                                "TYPE": "TEXT",
                                "VALUE": "RESET SETTINGS"
                        },
                        "RESET_APP_PREFERENCES": {
                                "TYPE": "TEXT",
                                "VALUE": "Reset app preferences"
                        },
                        "RESET_APPS": {
                                "TYPE": "TEXT",
                                "VALUE": "RESET APPS"
                        },
                        "LANGUAGES_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Languages"
                        },
                        "LANGUAGES_MENU_IN_SELECTED_LANGUAGE": {
                                "TYPE": "TEXT",
                                "VALUE": "Idiomas"
                        }
                },
                "SECURITY": {
                        "PATH": "Settings > Security",
                        "OPTIONS": [
                        ],
                        "TITLE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_title",
                                "PACKAGE": "com.android.car.settings.googlecarui.rro"
                        },
                        "CHOOSE_LOCK_TYPE": {
                                "TYPE": "TEXT",
                                "VALUE": "Choose a lock type"
                        },
                        "LOCK_TYPE_PASSWORD": {
                                "TYPE": "TEXT",
                                "VALUE": "Password"
                        },
                        "LOCK_TYPE_PIN": {
                                "TYPE": "TEXT",
                                "VALUE": "PIN"
                        },
                        "LOCK_TYPE_NONE": {
                                "TYPE": "TEXT",
                                "VALUE": "None"
                        },
                        "CONTINUE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Continue"
                        },
                        "CONFIRM_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Confirm"
                        },
                        "ENTER_PASSWORD": {
                                "TYPE": "CLASS",
                                "VALUE": "android.widget.EditText"
                        },
                        "PIN_PAD": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "pin_pad",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "ENTER_PIN_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "key_enter",
                                "PACKAGE": "com.android.car.settings"
                        },
                        "REMOVE_BUTTON": {
                                "TYPE": "TEXT",
                                "VALUE": "Remove"
                        }
                }
        },
        "PHONE": {
                "APPLICATION_CONFIG": {
                        "DIAL_PACKAGE": "com.android.car.dialer",
                        "PHONE_ACTIVITY": "com.android.car.dialer/.ui.TelecomActivity",
                        "OPEN_DIAL_PAD_COMMAND": "am start -a android.intent.action.DIAL"
                },
                "IN_CALL_VIEW": {
                        "DIALED_CONTACT_TITLE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "user_profile_title",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "DIALED_CONTACT_NUMBER": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "user_profile_phone_number",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "END_CALL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "end_call_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "MUTE_CALL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "mute_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "SWITCH_TO_DIAL_PAD": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "toggle_dialpad_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CHANGE_VOICE_CHANNEL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "voice_channel_view",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "VOICE_CHANNEL_CAR": {
                                "TYPE": "TEXT",
                                "VALUE": "Car speakers"
                        },
                        "VOICE_CHANNEL_PHONE": {
                                "TYPE": "TEXT",
                                "VALUE": "Phone"
                        }
                },
                "DIAL_PAD_VIEW": {
                        "DIAL_PAD_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Dial Pad"
                        },
                        "DIAL_PAD_FRAGMENT": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "dialpad_fragment",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "DIALED_NUMBER": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "MAKE_CALL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "call_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "DELETE_NUMBER": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "delete_button",
                                "PACKAGE": "com.android.car.dialer"
                        }
                },
                "CONTACTS_VIEW": {
                        "CONTACTS_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Contacts"
                        },
                        "CONTACT_INFO": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "call_action_id",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_DETAIL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "show_contact_detail_id",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "ADD_CONTACT_TO_FAVORITE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "contact_details_favorite_button",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "SEARCH_CONTACT": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "menu_item_search",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_SEARCH_BAR": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_ui_toolbar_search_bar",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "SEARCH_RESULT": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "contact_name",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_SETTINGS": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "menu_item_setting",
                                "PACKAGE": "com.android.car.dialer"
                        },
                        "CONTACT_ORDER": {
                                "TYPE": "TEXT",
                                "VALUE": "Contact order"
                        },
                        "SORT_BY_FIRST_NAME": {
                                "TYPE": "TEXT",
                                "VALUE": "First name"
                        },
                        "SORT_BY_LAST_NAME": {
                                "TYPE": "TEXT",
                                "VALUE": "Last Name"
                        },
                        "CONTACT_TYPE_WORK": {
                                "TYPE": "TEXT",
                                "VALUE": "Work"
                        },
                        "CONTACT_TYPE_MOBILE": {
                                "TYPE": "TEXT",
                                "VALUE": "Mobile"
                        },
                        "CONTACT_TYPE_HOME": {
                                "TYPE": "TEXT",
                                "VALUE": "Home"
                        }
                },
                "CALL_HISTORY_VIEW": {
                        "CALL_HISTORY_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Recents"
                        },
                        "CALL_HISTORY_INFO": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "call_action_id",
                                "PACKAGE": "com.android.car.dialer"
                        }
                },
                "FAVORITES_VIEW": {
                        "FAVORITES_MENU": {
                                "TYPE": "TEXT",
                                "VALUE": "Favorites"
                        }
                }
        },
        "NOTIFICATIONS": {
                "APPLICATION_CONFIG": {
                        "OPEN_NOTIFICATIONS_COMMAND": "service call statusbar 1"
                },
                "EXPANDED_NOTIFICATIONS_SCREEN": {
                        "NOTIFICATION_VIEW": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "notification_view",
                                "PACKAGE": "com.android.systemui"
                        },
                        "CLEAR_ALL_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "clear_all_button",
                                "PACKAGE": "com.android.systemui"
                        },
                        "STATUS_BAR": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "car_top_navigation_bar_container",
                                "PACKAGE": "com.android.systemui"
                        },
                        "APP_ICON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "app_icon",
                                "PACKAGE": "com.android.systemui"
                        },
                        "APP_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "header_text",
                                "PACKAGE": "com.android.systemui"
                        },
                        "NOTIFICATION_TITLE": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "notification_body_title",
                                "PACKAGE": "com.android.systemui"
                        },
                        "NOTIFICATION_BODY": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "notification_body_content",
                                "PACKAGE": "com.android.systemui"
                        },
                        "CARD_VIEW": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "card_view",
                                "PACKAGE": "com.android.systemui"
                        }
                }
        },
        "MEDIA_CENTER": {
                "APPLICATION_CONFIG": {
                        "MEDIA_CENTER_PACKAGE": "com.android.car.media",
                        "MEDIA_ACTIVITY": "com.android.bluetooth/com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService"
                },
                "MEDIA_CENTER_SCREEN": {
                        "PLAY_PAUSE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "play_pause_stop",
                                "PACKAGE": "com.android.car.media"
                        },
                        "NEXT_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_next",
                                "PACKAGE": "com.android.car.media"
                        },
                        "PREVIOUS_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_prev",
                                "PACKAGE": "com.android.car.media"
                        },
                        "SHUFFLE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "overflow_on",
                                "PACKAGE": "com.android.car.media"
                        },
                        "PLAY_QUEUE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "play_queue",
                                "PACKAGE": "com.android.car.media"
                        },
                        "MINIMIZED_MEDIA_CONTROLS": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "minimized_playback_controls",
                                "PACKAGE": "com.android.car.media"
                        },
                        "TRACK_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.media"
                        },
                        "TRACK_NAME_MINIMIZED_CONTROL": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "minimized_control_bar_title",
                                "PACKAGE": "com.android.car.media"
                        },
                        "BACK_BUTTON": {
                                "TYPE": "DESCRIPTION",
                                "VALUE": "Back"
                        }
                },
                "MEDIA_CENTER_ON_HOME_SCREEN": {
                        "PLAY_PAUSE_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "play_pause_stop",
                                "PACKAGE": "com.android.car.carlauncher"
                        },
                        "NEXT_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_next",
                                "PACKAGE": "com.android.car.carlauncher"
                        },
                        "PREVIOUS_BUTTON": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "skip_prev",
                                "PACKAGE": "com.android.car.carlauncher"
                        },
                        "TRACK_NAME": {
                                "TYPE": "RESOURCE_ID",
                                "VALUE": "title",
                                "PACKAGE": "com.android.car.carlauncher"
                        }
                }
        }
}
  

대체 기기 구성

다음 코드 샘플은 기본 설정이 DUT의 설정으로 재정의된 JSON 구성 파일의 예를 보여줍니다. 이 예는 다음과 같습니다.

  • 인터넷 설정 이름이 참조 기기에서는 네트워크 및 인터넷이고 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의 일련번호 ID입니다. 이 매개변수는 기기 한 대만 호스트에 연결된 경우 필요하지 않습니다.

  • PATH-TO-JSON-FILE: 호스트 머신의 JSON 파일 경로입니다.

구성 형식

구성에는 다음과 같은 키와 값이 있는 최상위 객체가 5개 있습니다.

객체 설명
PACKAGES 앱이 포그라운드에 있는 시점을 확인하는 데 사용되는 다양한 앱의 기본 패키지를 설명하는 객체입니다.
ACTIONS 다양한 작업의 작업 유형과 매개변수를 나타내는 객체입니다. 예를 들어 스크롤할 때 버튼을 사용할지 동작을 사용할지입니다.
COMMANDS 다양한 작업을 실행하는 명령어를 지정하는 객체입니다.
UI_ELEMENTS UI 요소를 선택하는 UI Automator `BySelectors` 를 구성하는 데 사용되는 객체입니다 (자세한 내용은 아래 참고).
WORKFLOWS 높은 수준의 작업을 완료하는 작업 시퀀스 (아래에 자세히 설명)

UI 요소

각 UI 요소에는 UI Automator가 요소를 식별하기 위해 검색할 항목 (예: 리소스 ID, 텍스트, 설명)과 해당 유형과 연결된 구성 값을 지정하는 TYPE가 있습니다. 일반적으로 지원 기능이 이 구성을 사용하여 화면의 요소를 식별할 때마다 정확히 하나의 요소를 가져옵니다. 여러 요소가 구성과 일치하면 테스트에서 임의의 요소가 사용됩니다. 따라서 구성은 관련 컨텍스트에서 하나의 요소로 좁혀질 만큼 구체적으로 작성해야 합니다 (일반적으로).

텍스트

가장 간단한 UI 요소 유형입니다. UI 요소는 텍스트로 식별되며 정확하게 일치해야 합니다.

    "CALL_HISTORY_MENU": {
      "TYPE": "TEXT",
      "VALUE": "Recents"
    }

TEXT_CONTAINS

TEXT와 동일하지만 지정된 VALUE은 일치시킬 요소의 텍스트에 어딘가에만 표시되면 됩니다.

    "PRIVACY_CALENDAR": {
      "TYPE": "TEXT_CONTAINS",
      "VALUE": "Calendar"
    }

설명

콘텐츠 설명 속성으로 요소를 식별하며 정확히 일치해야 합니다.

    "APP_GRID_SCROLL_BACKWARD_BUTTON": {
      "TYPE": "DESCRIPTION",
      "VALUE": "Scroll up"
    }

RESOURCE_ID

리소스 ID로 요소를 식별하고 선택적으로 해당 ID의 패키지 구성요소도 확인합니다. PACKAGE 키는 선택사항입니다. 생략하면 모든 패키지가 일치하며 :id/ 뒤에 오는 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"
          }
        }
      ]
    }

이 예시에서 구성은 깊이 2에 하위 요소가 있고 텍스트가 Permission managerRelativeLayout를 식별합니다.

워크플로

워크플로는 특정 작업을 완료하는 데 사용되는 일련의 작업을 나타내며, 기기 유형에 따라 충분히 다를 수 있고 코드보다 구성에서 나타내는 것이 더 유연합니다.

    "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 요소 항목과 동일한 형식을 취하는 UI_ELEMENT 키가 있는 객체입니다 (위 참고). 이러한 유형은 다음과 같습니다.

PRESS
LONG_PRESS
CLICK
LONG_CLICK
CLICK_IF_EXIST
HAS_UI_ELEMENT_IN_FOREGROUND
SCROLL_TO_FIND_AND_CLICK
SCROLL_TO_FIND_AND_CLICK_IF_EXIST
SWIPE_TO_FIND_AND_CLICK
SWIPE_TO_FIND_AND_CLICK_IF_EXIST

다른 유형의 구성 세부정보는 다음과 같습니다.

객체 설명
COMMAND 실행할 명령어가 포함된 TEXT 값이 있는 객체입니다.
HAS_PACKAGE_IN_FOREGROUND 패키지가 포함된 TEXT 값이 있는 객체
SWIPE SWIPE 작업의 CONFIG key를 생략합니다. 이 예에서는 SWIPE_CONFIG만 사용합니다.
WAIT_MS 대기할 밀리초 수를 포함하는 TEXT 값이 있는 객체입니다.

스크롤 및 스와이프 관련 작업에는 다음과 같이 추가 구성이 필요합니다.

SCROLL_CONFIG

객체 설명
SCROLL_ACTION USE_GESTURE 또는 USE_BUTTON
SCROLL_DIRECTION HORIZONTAL 또는 VERTICAL
SCROLL_ELEMENT UI 요소 구성과 동일한 형식을 사용하여 스크롤할 컨테이너를 나타내는 객체입니다 (위 참고).
SCROLL_FORWARD, SCROLL_BACKWARD 앞으로 및 뒤로 스크롤 버튼 (SCROLL_ACTIONUSE_BUTTON인 경우 필요).
SCROLL_MARGIN SCROLL_ACTIONUSE_GESTURE인 경우 스크롤을 실행하는 데 사용될 드래그를 시작하고 중지할 컨테이너의 가장자리까지의 거리입니다 (선택사항, 기본값 = 10).
SCROLL_WAIT_TIME SCROLL_ACTIONUSE_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: 테스트할 앱의 이름입니다. 예를 들어 Android.bp 파일에 지정된 대로 TEST-APK-NAMEAndroidAutomotiveSettingsTests로 설정하여 Wi-Fi 설정을 테스트합니다. APK의 이름은 자동차 테스트의 각 Android.bp 파일에서 확인할 수 있습니다.

  • DEVICE-SERIAL: DUT의 일련번호 ID입니다. 이 매개변수는 기기 한 대만 호스트에 연결된 경우 필요하지 않습니다.

  • config-file-path: JSON 구성 파일에 지정된 대로 기본이 아닌 기기 UI 구성을 제공하는 목적으로만 필요한 선택적 매개변수입니다. 제공되지 않으면 Spectatio 프레임워크는 기본값을 사용하여 테스트를 실행합니다.

  • PATH-FOR-BUILT-TEST-APK: make 명령어가 실행될 때 테스트 APK가 빌드되는 경로입니다.

  • TEST-PACKAGE: 테스트 패키지의 이름입니다.

  • TEST-CLASSNAME: 테스트 클래스의 이름입니다. 예를 들어 Wi-Fi 설정 테스트의 경우 테스트 패키지는 android.platform.tests이며 테스트 클래스 이름은 WifiSettingTest입니다.

자동차 스니펫 라이브러리

Automotive 스니펫 라이브러리는 자동차 앱 및 서비스와 상호작용하도록 설계된 Android 오픈소스 프로젝트 (AOSP)용 Android 테스트 라이브러리 집합입니다. 호스트 (테스트) 머신에서 Android 기반 기기로 원격 프로시저 호출 (RPC)을 실행하는 편리한 메커니즘을 사용하여 Spectatio를 활용합니다.

시작하기

시작하기 전에 다음 섹션을 검토하세요.

기본 요건

  • 호스트 머신에 Python 3.x가 설치되어 있어야 합니다.
  • 필요한 빌드 도구가 포함된 AOSP 환경 설정
  • adb 액세스 권한이 있는 Android Automotive 기기 (에뮬레이터 또는 실제 기기)

컴파일

Automotive 스니펫 라이브러리에서 제공하는 다양한 스니펫을 컴파일하려면 제공된 android.bp 파일을 사용하면 됩니다. 이전 섹션의 명령어를 따라 APK를 컴파일합니다.

배포

스니펫 라이브러리를 컴파일한 후 이전 섹션에 설명된 adb install 명령어를 사용하여 결과 APK를 타겟 기기에 배포합니다.

테스트 실행

스니펫 라이브러리는 자동차 시스템과 상호작용하는 여러 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: 다이얼링, 볼륨 제어, 차량 하드 키, 미디어 센터 상호작용 등 차량 작동과 관련된 API를 제공합니다.

  • PhoneSnippet: 통화 처리, 연락처 탐색, SMS 작업 등 전화 통신 관련 API를 제공합니다.

자동차 스니펫과 전화 스니펫은 몇 가지 공통 로직을 공유합니다. 특히 블루투스 관련 RCP 호출을 침입하여 자동차와 휴대전화 기기를 페어링할 수 있습니다. 이 bt_discovery_test에서 방법을 확인할 수 있습니다.