Espresso-Intents

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

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

프로젝트에 Espresso-Intents 포함

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

Groovy

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

Kotlin

androidTestImplementation('androidx.test.espresso:espresso-intents:3.4.0')

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

Groovy

androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:rules:1.4.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

Kotlin

androidTestImplementation('androidx.test:runner:1.4.0')
androidTestImplementation('androidx.test:rules:1.4.0')
androidTestImplementation('androidx.test.espresso:espresso-core:3.4.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)

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")

Java

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

Java

@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)
    

    Java

    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)
    

    Java

    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)))
    

    Java

    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)))
}

Java

@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: 사용자가 카메라를 사용하여 비트맵을 가져오는 과정을 시뮬레이션합니다.