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의 앱 도우미 구현 함수를 참고하세요.

Automotive 테스트는 앱 도우미 구현 함수를 사용하여 앱과 관련된 다양한 작업을 테스트합니다. 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

지정된 VALUE가 일치할 요소의 텍스트 어딘가에만 표시되어야 한다는 점을 제외하고는 TEXT와 동일합니다.

    "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"
          }
        }
      ]
    }

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

워크플로

워크플로는 특정 작업을 완료하는 데 사용되는 일련의 작업을 나타냅니다. 이는 기기 유형마다 충분히 다를 수 있으며 코드보다 구성에서 더 유연하게 표현할 수 있습니다.

    "WORKFLOWS": {
    "OPEN_SOUND_SETTINGS_WORKFLOW": [
      {
        "NAME": "Go to Home",
        "TYPE": "PRESS",
        "CONFIG": {
          "TEXT": "HOME"
        }
      },
      {
        "NAME": "Open Settings",
        "TYPE": "COMMAND",
        "CONFIG": {
          "TEXT": "am start -a android.settings.SETTINGS"
        }
      },
      {
        "NAME": "Open Sound Settings",
        "TYPE": "SCROLL_TO_FIND_AND_CLICK",
        "CONFIG": {
          "UI_ELEMENT": {
            "TYPE": "TEXT",
            "VALUE": "Sound"
          }
        },
        "SCROLL_CONFIG": {
          "SCROLL_ACTION": "USE_GESTURE",
          "SCROLL_DIRECTION": "VERTICAL",
          "SCROLL_ELEMENT": {
            "TYPE": "RESOURCE_ID",
            "VALUE": "car_ui_recycler_view"
          }
        }
      }
    ]
  }

각 워크플로는 키-값 쌍이며 키는 워크플로의 이름이고 값은 실행할 작업 배열입니다. 각 작업에는 NAME, TYPE, 일반적으로 CONFIG, 경우에 따라 SWIPE_CONFIG 또는 SCROLL_CONFIG가 있습니다. 대부분의 TYPE의 경우 CONFIG는 값이 UI 요소 항목과 동일한 형식을 취하는 UI_ELEMENT 키가 있는 객체입니다 (위 참고). 이러한 TYPE은 다음과 같습니다.

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

다른 TYPE의 경우 구성 세부정보는 다음과 같습니다.

객체 설명
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_BACKWARD SCROLL_FORWARD 앞뒤 스크롤 버튼 (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 구성을 제공하는 목적으로만 필요한 선택적 매개변수입니다. 제공되지 않으면 프레임워크는 테스트 실행을 위해 기본값을 사용합니다.

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

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

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

Automotive 스니펫 라이브러리

Automotive Snippet Library는 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를 제공합니다.

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