안드로이드 Espresso Recorder 활용한 UI 테스트



개인 광고 영역

Google에서 제공하는 UI 테스트 방법은 Espresso을 이용할 수 있고, 전역에서 간단하게 테스트 가능한 UI Automator를 제공하고 있다.

그리고 좀 더 테스트를 편하게 제공하기 위해서 Android Studio에서 제공하는 Espresso Recorder가 있다.

이번 글에서는 Espresso Recorder를 알아보자.

Espresso Recorder

Espresso Recorder(Google Document)는 Android Studio에 포함되어있는 기능으로, Espresso SDK를 활용하여 UI 테스트를 간단하게 도와주는 기능을 제공한다.

Espresso Record 소개 및 이전 강의 영상

예전에 찍어둔 영상이지만 Espresso Recorder의 사용법은 동일하여 영상을 추가한다.

Android Studio 2.3에서 테스트한 내용으로 현재와는 차이가 있다.


Espresso Recorder 사용하기

Espresso Recorder는 Android Studio 2.3부터 제공했고, 사용방법은 간단하다.

Android Studio를 실행하고, Run > Record Espresso Test를 눌러 실행할 수 있다.

sample_01

Record Espresso Test를 누르면 기기에 앱을 설치하고, 레코드를 대기한다.

대기 후 아래와 같이 버튼 클릭 및 데이터 체크가 가능하다.

sample_02


Espresso Recorder 활용 주요 코드

주요 코드는 아래와 같다. onView를 통해 화면에 그려진 recycler_view를 찾고, 이 recycler_view가 ConstraintLayout의 자식인지를 체크하는 로직을 포함하고 있다.

ConstraintLayout의 0번째 child 임을 확인하고 0번째 아이템을 누르도록 코드가 완성되었다.

val recyclerView = onView(
    allOf(
        withId(R.id.recycler_view),
        childAtPosition(
            withClassName(`is`("android.support.constraint.ConstraintLayout")),
            0
        )
    )
)
recyclerView.perform(actionOnItemAtPosition<ViewHolder>(0, click()))

그리고 childAtPosition은 아래와 같은 코드를 자동으로 완성해주고 있다. 이 코드를 통해 View를 찾아 return true를 리턴하게 되어있다.

private fun childAtPosition(
    parentMatcher: Matcher<View>, position: Int
): Matcher<View> {

    return object : TypeSafeMatcher<View>() {
        override fun describeTo(description: Description) {
            description.appendText("Child at position $position in parent ")
            parentMatcher.describeTo(description)
        }

        public override fun matchesSafely(view: View): Boolean {
            val parent = view.parent
            return parent is ViewGroup && parentMatcher.matches(parent)
                    && view == parent.getChildAt(position)
        }
    }
}

결국 화면의 구조가 변경되었거나, 화면에 View가 그려지지 않는 경우에는 위 코드가 동작하지 않는다.


Espresso Record를 이용해 동작 확인

녹화 화면을 한번 보자. 녹화 화면의 시나리오는 아래와 같다.

시나리오 1.

  1. 메인 화면에서 0 번째 이미지를 누른다.
  2. 0번째 이미지의 상세화면 노출 시 메시지를 확인한다.

이에 대한 영상인데 아래와 같다.

sample_03


그래서 화면에 그려지지 않을 경우

위 화면에서 볼 수 있듯이, 사진이 나오기 전에 종료되었다. 결국 테스트는 fail로 떨어지게 되었음을 알 수 있는데, 로그에서 다음과 같은 걸 확인할 수 있다.

android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: (with text: is "Trio of Trivelle Pasta (245/365)" and Child at position 1 in parent (with id: tech.thdev.flickr.example.debug:id/toolbar and Child at position 1 in parent an instance of android.view.ViewGroup) and is displayed on the screen to the user)

View Hierarchy:
+>DecorView{id=-1, visibility=VISIBLE, width=1440, height=2880, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params={(0,0)(fillxfill) ty=BASE_APPLICATION wanim=0x10302fe ... }}

위 오류는 Espresso Recorder 활용 주요 코드에서 확인했던 View Hierarchy 확인에서 false 리턴으로 생긴 부분이다.

결국 화면이 다 그려지지 않은 상태로 테스트가 종료되었기 때문이다.


해결하려면?

Espresso Record를 활용한다는 건 어디까지나 편하게 UI 테스트에 접근하기 위해서인데 async 동작에서는 테스트하기 어려움을 확인할 수 있다.

결국 비동기 처리를 위해서는 Thread.sleep과 같은 대기 상태를 만들어야 한다.

다음 글에 이를 해결하는 자세한 방법을 알아볼 텐데 여기서는 Thread.sleep을 임의로 주고 해결할 수 있다.


마무리

다음 글에서 Espresso Recorder 대신 직접 코드를 적어서 간단하게 처리하는 방법을 살펴보겠다.



About Taehwan

My name is Taehwan Kwon. I have developed Android for 6 years and blog has been active for eight years.

Comments