Espresso Web

Espresso-Web은 Android WebView UI 구성요소를 사용하기 위한 진입점입니다. Espresso-Web은 인기 WebDriver API의 Atom을 재사용하여 WebView의 동작을 검사하고 제어합니다.

Espresso-Web 사용 시기

하이브리드 앱, 특히 앱의 네이티브 UI 구성요소와 WebView UI 구성요소의 통합을 테스트하려면 Espresso-Web을 사용합니다. Espresso-Web API를 다른 Espresso API와 함께 사용하여 WebView객체 내부의 웹 요소와 완벽하게 상호작용할 수 있습니다.

WebView와 앱의 네이티브 구성요소 간 상호작용이 아니라 WebView 자체만 테스트해야 하면 WebDriver와 같은 프레임워크를 사용하여 일반 웹 테스트를 작성해 보세요. 웹 테스트 프레임워크를 사용하면 Android 기기 또는 자바 가상 머신을 사용할 필요가 없으므로 테스트를 더 빠르고 안정적으로 실행할 수 있습니다. 하지만 Espresso-Web을 사용하면 맞춤 WebDriver Atom을 재사용할 수 있으므로 특히 독립형 웹 앱 및 Android UI를 포함하는 앱에 관해 실행할 테스트를 작성할 때 유연성이 향상됩니다.

작동 방식

Espresso의 onData() 메서드와 유사하게 WebView 상호작용은 여러 개의 Atom으로 구성됩니다. WebView 상호작용은 자바 프로그래밍 언어와 자바스크립트 브리지의 조합을 사용하여 작업을 실행합니다. 자바 기반 측면에서 Espresso에 표시되는 모든 항목은 격리된 사본이기 때문에 자바스크립트 환경에서 데이터를 노출하여 경합 상태가 발생할 가능성이 없으므로 Web.WebInteraction 객체에서 데이터를 반환하는 것이 완벽히 지원되며 이에 따라 요청에서 반환된 모든 데이터를 확인할 수 있습니다.

WebDriver Atom이란?

WebDriver 프레임워크는 Atom을 사용하여 프로그래매틱 방식으로 웹 요소를 찾고 조작합니다. Atom은 WebDriver에서 브라우저 조작을 허용하는 데 사용됩니다. Atom은 개념적으로 UI에서 작업을 실행하는 독립적인 단위인 ViewAction과 유사합니다. findElement()getElement()와 같은 정의된 메서드 목록을 통해 Atom을 노출하여 사용자 관점에서 브라우저를 구동합니다. 그러나 WebDriver 프레임워크를 직접 사용하면 Atom이 적절하게 조정되어야 하므로 매우 상세한 로직이 필요합니다.

Espresso 내에서 WebWeb.WebInteraction 클래스는 이 상용구를 래핑하고 Espresso에서 WebView 객체와 상호작용하는 것과 같은 느낌을 줍니다. 따라서 WebView의 컨텍스트에서 Atom은 기존 Espresso ViewMatchersViewActions를 대체하여 사용됩니다.

그러면 다음과 같이 API가 매우 단순해집니다.

Kotlin

    onWebView()
        .withElement(Atom)
        .perform(Atom)
        .check(WebAssertion)
    

자바

    onWebView()
        .withElement(Atom)
        .perform(Atom)
        .check(WebAssertion);
    

자세히 알아보려면 Atom에 관한 Selenium 문서를 읽어보세요.

WebView 구현

다음 섹션의 안내에 따라 앱 테스트에서 WebView를 사용하세요.

패키지

Espresso-Web을 프로젝트에 포함하려면 다음 단계를 완료하세요.

  1. 앱의 build.gradle 파일을 엽니다. 이 파일은 일반적으로 최상위 수준의 build.gradle 파일이 아니라 app/build.gradle입니다.
  2. 종속 항목 내부에 다음 행을 추가합니다.

        androidTestImplementation 'androidx.test.espresso:espresso-web:3.1.0'
        
  3. Espresso-Web은 Espresso 2.2 이상 및 버전 0.3 이상의 테스트 라이브러리와만 호환되므로 해당하는 줄도 업데이트해야 합니다.

        androidTestImplementation 'androidx.test:runner:1.1.0'
        androidTestImplementation 'androidx.test:rules:1.1.0'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
        

일반적인 API 사용

onWebView() 메서드는 Espresso를 사용하여 Android에서 WebView로 작업할 때 기본 진입점입니다. 이 메서드를 사용하여 다음과 같은 Espresso-Web 테스트를 실행할 수 있습니다.

Kotlin

    onWebView()
        .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...))
        .perform(webClick()) // Similar to perform(click())

        // Similar to check(matches(...))
        .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")))
    

자바

    onWebView()
        .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...))
        .perform(webClick()) // Similar to perform(click())

        // Similar to check(matches(...))
        .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")));
    

이 예에서는 Espresso-Web이 ID가 "link_2"인 DOM 요소를 찾아서 클릭합니다. 그런 다음, 이 도구는 WebView가 "navigation_2.html" 문자열을 포함하는 GET 요청을 보내는지 확인합니다.

자바스크립트 지원

테스트를 실행할 때 시스템에서 자바스크립트를 사용하여 모든 WebView 상호작용을 실행합니다. 따라서 자바스크립트 평가를 지원하려면 테스트 중인 WebView에서 자바 스크립트가 사용 설정되어 있어야 합니다.

다음 코드 스니펫에서와 같이 forceJavascriptEnabled()테스트 중인 활동의 작업으로 호출하여 자바스크립트를 강제로 사용 설정할 수 있습니다.

    @RunWith(AndroidJUnit4::class)
    class MyTestSuite {
        @get:Rule val activityScenarioRule =
            activityScenarioRule<MyWebViewActivity>()

        @Test fun testWebViewInteraction() {
            onWebView().forceJavascriptEnabled()
        }
    }
    

일반적인 웹 상호작용

Web.WebInteraction 객체와의 일반적인 상호작용에는 다음이 포함됩니다.

  • withElement()는 WebView 내에서 DOM 요소를 참조합니다.

    예:

    Kotlin

        onWebView().withElement(findElement(Locator.ID, "teacher"))
        

    자바

        onWebView().withElement(findElement(Locator.ID, "teacher"));
        
  • withContextualElement()는 WebView 내에서 다른 DOM 요소와 관련하여 범위 지정된 DOM 요소를 참조합니다. 참조 Web.WebInteraction 객체(DOM 요소)를 설정하려면 먼저 withElement()를 호출해야 합니다.

    예:

    Kotlin

        .withElement(findElement(Locator.ID, "teacher"))
            .withContextualElement(findElement(Locator.ID, "person_name"))
        

    자바

        .withElement(findElement(Locator.ID, "teacher"))
            .withContextualElement(findElement(Locator.ID, "person_name"));
        
  • check()는 조건을 평가하여 true로 분석되는지 확인합니다.

    예:

    Kotlin

        onWebView()
            .withElement(findElement(Locator.ID, "teacher"))
            .withContextualElement(findElement(Locator.ID, "person_name"))
            .check(webMatches(getText(), containsString("Socrates")))
        

    자바

        onWebView()
            .withElement(findElement(Locator.ID, "teacher"))
            .withContextualElement(findElement(Locator.ID, "person_name"))
            .check(webMatches(getText(), containsString("Socrates")));
        
  • perform()은 WebView 내에서 요소 클릭과 같은 작업을 실행합니다.

    예:

    Kotlin

        onWebView()
            .withElement(findElement(Locator.ID, "teacher"))
            .perform(webClick())
        

    자바

        onWebView()
            .withElement(findElement(Locator.ID, "teacher"))
            .perform(webClick());
        
  • reset()은 WebView를 초기 상태로 되돌립니다. 이 상호작용은 클릭과 같은 선행 작업으로 인해 ElementReference 및 WindowReference 객체에 액세스할 수 없게 만드는 탐색 변경이 발생하는 때에 필요합니다.

    참고: reset()을 사용하면 양식 제출과 같은 다중 페이지 워크플로에 관해 어설션할 때 유용하지만 일반적으로 테스트 범위가 제한되고 테스트 시 단일 페이지에 중점을 두어야 합니다.

    예:

    Kotlin

        onWebView()
            .withElement(...)
            .perform(...)
            .reset()
        

    자바

        onWebView()
            .withElement(...)
            .perform(...)
            .reset();
        

다음 예에서는 WebView에 텍스트를 입력하고 Submit 버튼을 선택한 후 동일한 WebView의 다른 요소 내에 동일한 텍스트가 표시되는지 테스트합니다.

Kotlin

    const val MACCHIATO = "Macchiato"

    @RunWith(AndroidJUnit4::class)
    class MyEspressoWebTestSuite {

        @Test fun typeTextInInput_clickButton_SubmitsForm() {
            // Create an intent that displays a web form.
            val webFormIntent = Intent()
            // ...

            // Lazily launch the Activity with a custom start Intent per test.
            ActivityScenario.launchActivity(webFormIntent)

            // Selects the WebView in your layout. If you have multiple WebView
            // objects, you can also use a matcher to select a given WebView,
            // onWebView(withId(R.id.web_view)).
            onWebView()
                // Find the input element by ID.
                .withElement(findElement(Locator.ID, "text_input"))

                // Clear previous input and enter new text into the input element.
                .perform(clearElement())
                .perform(DriverAtoms.webKeys(MACCHIATO))

                // Find the "Submit" button and simulate a click using JavaScript.
                .withElement(findElement(Locator.ID, "submitBtn"))
                .perform(webClick())

                // Find the response element by ID, and verify that it contains the
                // entered text.
                .withElement(findElement(Locator.ID, "response"))
                .check(webMatches(getText(), containsString(MACCHIATO)))
        }
    }
    

자바

    public static final String MACCHIATO = "Macchiato";

    @Test
    public void typeTextInInput_clickButton_SubmitsForm() {
        // Create an intent that displays a web form.
        Intent webFormIntent = new Intent();
        // ...

        // Lazily launch the Activity with a custom start Intent per test.
        ActivityScenario.launchActivity(webFormIntent);

        // Selects the WebView in your layout. If you have multiple WebView objects,
        // you can also use a matcher to select a given WebView,
        // onWebView(withId(R.id.web_view)).
        onWebView()
            // Find the input element by ID.
            .withElement(findElement(Locator.ID, "text_input"))

            // Clear previous input and enter new text into the input element.
            .perform(clearElement())
            .perform(DriverAtoms.webKeys(MACCHIATO))

            // Find the "Submit" button and simulate a click using JavaScript.
            .withElement(findElement(Locator.ID, "submitBtn"))
            .perform(webClick())

            // Find the response element by ID, and verify that it contains the
            // entered text.
            .withElement(findElement(Locator.ID, "response"))
            .check(webMatches(getText(), containsString(MACCHIATO)));
    }
    

참고 자료

Android 테스트에서 Espresso-Web을 사용하는 방법에 관한 자세한 내용은 다음 자료를 참조하세요.

샘플

  • WebBasicSample: Espresso-Web을 사용하여 WebView 객체와 상호작용합니다.