Espresso-Intents

Espresso-Intents는 Espresso의 확장 프로그램이며, 테스트 중인 애플리케이션에서 전송된 인텐트의 유효성 검사 및 스터브를 가능하게 합니다. Mockito와 유사하지만 Android 인텐트에 사용됩니다.

앱이 다른 앱 또는 플랫폼에 기능을 위임하면 다른 앱 또는 플랫폼이 올바르게 작동한다고 가정하고 Espresso-Intents를 사용하여 자체 앱 로직에 집중할 수 있습니다. Espresso-Intents를 사용하면 발신 인텐트를 일치시키고 유효성 검사하거나 실제 인텐트 응답 대신 스터브 응답을 제공할 수도 있습니다.

프로젝트에 Espresso-Intents 포함

앱의 app/build.gradle 파일에서 dependencies 내에 다음 행을 추가합니다.

androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.0'
    

Espresso-Intents는 Espresso 2.1 이상 및 버전 0.3 이상의 Android 테스트 라이브러리와만 호환되므로 그러한 행도 업데이트해야 합니다.

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

테스트 규칙 작성

Espresso-Intents 테스트를 작성하기 전에 IntentsTestRule을 설정합니다. 이는 ActivityTestRule 클래스의 확장이며 기능적 UI 테스트에서 Espresso-Intents API를 쉽게 사용할 수 있도록 합니다. IntentsTestRule@Test 주석이 달린 각 테스트 전에 Espresso-Intents를 초기화하고 각 테스트 실행 후 Espresso-Intents를 해제합니다.

다음 코드 스니펫은 IntentsTestRule의 예입니다.

Kotlin

    @get:Rule
    val intentsTestRule = IntentsTestRule(MyActivity::class.java)
    

자바

    @Rule
    public IntentsTestRule<MyActivity> intentsTestRule =
        new IntentsTestRule<>(MyActivity.class);
    

일치

Espresso-Intents는 Hamcrest 매처를 사용하여 정의된 특정 일치 기준에 따라 발신 인텐트를 가로챌 수 있는 기능을 제공합니다. Hamcrest을 사용하면 다음 작업이 가능합니다.

  • 기존 인텐트 매처 사용: 거의 모든 경우에 선호되는 가장 쉬운 옵션입니다.
  • 자체 인텐트 매처 구현: 가장 유연한 옵션입니다. 자세한 내용은 Hamcrest 가이드 내의 '맞춤 매처 작성'이라는 섹션에 있습니다.

Espresso-Intents는 인텐트 유효성 검사 및 스터브를 위해 각각 intended()intending() 메서드를 제공합니다. 두 메서드 모두 Hamcrest Matcher<Intent> 객체를 인수로 사용합니다.

다음 코드 스니펫은 기존 인텐트 매처를 사용하는 인텐트 유효성 검사를 보여줍니다. 이 인텐트 매처는 브라우저를 시작하는 발신 인텐트를 일치시킵니다.

Kotlin

    assertThat(intent).hasAction(Intent.ACTION_VIEW)
    assertThat(intent).categories().containsExactly(Intent.CATEGORY_BROWSABLE)
    assertThat(intent).hasData(Uri.parse("www.google.com"))
    assertThat(intent).extras().containsKey("key1")
    assertThat(intent).extras().string("key1").isEqualTo("value1")
    assertThat(intent).extras().containsKey("key2")
    assertThat(intent).extras().string("key2").isEqualTo("value2")
    

자바

    assertThat(intent).hasAction(Intent.ACTION_VIEW);
    assertThat(intent).categories().containsExactly(Intent.CATEGORY_BROWSABLE);
    assertThat(intent).hasData(Uri.parse("www.google.com"));
    assertThat(intent).extras().containsKey("key1");
    assertThat(intent).extras().string("key1").isEqualTo("value1");
    assertThat(intent).extras().containsKey("key2");
    assertThat(intent).extras().string("key2").isEqualTo("value2");
    

인텐트 유효성 검사

Espresso-Intents는 테스트 중인 애플리케이션에서 활동을 시작하려는 모든 인텐트를 기록합니다. Mockito.verify()와 유사한 intended() 메서드를 사용하여 지정된 인텐트가 표시되었는지 어설션할 수 있습니다. 하지만 이렇게 하도록 명시적으로 구성하지 않으면 Espresso-Intents는 인텐트에 관한 응답을 스터브하지 않습니다.

다음 코드 스니펫은 외부 '휴대전화' 활동을 시작하는 발신 인텐트의 유효성을 검사하지만 이 인텐트에 관한 응답을 스터브하지 않는 예제 테스트입니다.

Kotlin

    @Test fun validateIntentSentToPackage() {
        // User action that results in an external "phone" activity being launched.
        user.clickOnView(system.getView(R.id.callButton))

        // Using a canned RecordedIntentMatcher to validate that an intent resolving
        // to the "phone" activity has been sent.
        intended(toPackage("com.android.phone"))
    }
    

자바

    @Test
    public void validateIntentSentToPackage() {
        // User action that results in an external "phone" activity being launched.
        user.clickOnView(system.getView(R.id.callButton));

        // Using a canned RecordedIntentMatcher to validate that an intent resolving
        // to the "phone" activity has been sent.
        intended(toPackage("com.android.phone"));
    }
    

스터브

Mockito.when()과 유사한 intending() 메서드를 사용하여 startActivityForResult()로 시작된 활동에 관한 스터브 응답을 제공할 수 있습니다. 외부 활동의 사용자 인터페이스를 조작할 수 없고 테스트 중인 활동에 반환되는 ActivityResult를 제어할 수 없으므로 이 메서드는 외부 활동에 특히 유용합니다.

다음 코드 스니펫은 사용자가 테스트 중인 앱에서 '연락처' 활동을 시작할 때 연락처 전화번호가 표시되는지 확인하는 activityResult_DisplaysContactsPhoneNumber() 테스트 예를 구현합니다.

  1. 특정 활동이 시작될 때 반환할 결과를 빌드합니다. 테스트 예에서는 '연락처'로 전송된 모든 인텐트를 가로채고 결과 코드 RESULT_OK를 사용하여 유효한 ActivityResult로 응답을 스터브합니다.

    Kotlin

        val resultData = Intent()
        val phoneNumber = "123-345-6789"
        resultData.putExtra("phone", phoneNumber)
        val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData)
        

    자바

        Intent resultData = new Intent();
        String phoneNumber = "123-345-6789";
        resultData.putExtra("phone", phoneNumber);
        ActivityResult result =
            new ActivityResult(Activity.RESULT_OK, resultData);
        
  2. Espresso에 '연락처' 인텐트의 모든 호출에 관한 응답으로 스텁 결과 개체를 제공하도록 지시합니다.

    Kotlin

        intending(toPackage("com.android.contacts")).respondWith(result)
        

    자바

        intending(toPackage("com.android.contacts")).respondWith(result);
        
  3. 활동을 시작하는 데 사용된 작업이 예상 스텁 결과를 생성하는지 확인합니다. 이 경우 예제 테스트에서 '연락처 활동'이 시작될 때 전화번호 '123-345-6789'가 반환되고 표시되는지 확인합니다.

    Kotlin

        onView(withId(R.id.pickButton)).perform(click())
        onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)))
        

    자바

        onView(withId(R.id.pickButton)).perform(click());
        onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)));
        

다음은 전체 activityResult_DisplaysContactsPhoneNumber() 테스트입니다.

Kotlin

    @Test fun activityResult_DisplaysContactsPhoneNumber() {
        // Build the result to return when the activity is launched.
        val resultData = Intent()
        val phoneNumber = "123-345-6789"
        resultData.putExtra("phone", phoneNumber)
        val result = Instrumentation.ActivityResult(Activity.RESULT_OK, resultData)

        // Set up result stubbing when an intent sent to "contacts" is seen.
        intending(toPackage("com.android.contacts")).respondWith(result)

        // User action that results in "contacts" activity being launched.
        // Launching activity expects phoneNumber to be returned and displayed.
        onView(withId(R.id.pickButton)).perform(click())

        // Assert that the data we set up above is shown.
        onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)))
    }
    

자바

    @Test
    public void activityResult_DisplaysContactsPhoneNumber() {
        // Build the result to return when the activity is launched.
        Intent resultData = new Intent();
        String phoneNumber = "123-345-6789";
        resultData.putExtra("phone", phoneNumber);
        ActivityResult result =
            new ActivityResult(Activity.RESULT_OK, resultData);

        // Set up result stubbing when an intent sent to "contacts" is seen.
        intending(toPackage("com.android.contacts")).respondWith(result);

        // User action that results in "contacts" activity being launched.
        // Launching activity expects phoneNumber to be returned and displayed.
        onView(withId(R.id.pickButton)).perform(click());

        // Assert that the data we set up above is shown.
        onView(withId(R.id.phoneNumber)).check(matches(withText(phoneNumber)));
    }
    

참고 자료

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

샘플

  • IntentsBasicSample: intended()intending()의 기본 사용법입니다.
  • IntentsAdvancedSample: 사용자가 카메라를 사용하여 비트맵을 가져오는 과정을 시뮬레이션합니다.