Эспрессо-Намерения

Espresso-Intents — это расширение Espresso, которое позволяет проверять и заглушать намерения , отправленные тестируемым приложением. Это похоже на Mockito , но для Android Intents.

Если ваше приложение делегирует функциональность другим приложениям или платформе, вы можете использовать Espresso-Intents, чтобы сосредоточиться на логике вашего собственного приложения, предполагая, что другие приложения или платформа будут работать правильно. С помощью Espresso-Intents вы можете сопоставлять и проверять свои исходящие намерения или даже предоставлять незавершенные ответы вместо фактических ответов о намерениях.

Включите Espresso-Intents в свой проект

В файле app/build.gradle вашего приложения добавьте следующую строку внутри dependencies :

классный

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

Котлин

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

Espresso-Intents совместим только с Espresso 2.1+ и версией 0.3+ библиотек тестирования Android, поэтому обязательно обновите и эти строки:

классный

androidTestImplementation 'androidx.test:runner:1.6.1'
androidTestImplementation 'androidx.test:rules:1.6.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'

Котлин

androidTestImplementation('androidx.test:runner:1.6.1')
androidTestImplementation('androidx.test:rules:1.6.1')
androidTestImplementation('androidx.test.espresso:espresso-core:3.6.1')

Напишите правила тестирования

Прежде чем писать тест Espresso-Intents, настройте IntentsTestRule . Это расширение класса ActivityTestRule , которое упрощает использование API-интерфейсов Espresso-Intents в функциональных тестах пользовательского интерфейса. IntentsTestRule инициализирует Espresso-Intents перед каждым тестом, помеченным @Test и освобождает Espresso-Intents после каждого запуска теста.

Следующий фрагмент кода является примером IntentsTestRule :

Котлин

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

Ява

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

Соответствовать

Espresso-Intents предоставляет возможность перехватывать исходящие намерения на основе определенных критериев соответствия, которые определяются с помощью Hamcrest Matchers. Хамкрест позволяет:

  • Использовать существующее средство сопоставления намерений: самый простой вариант, которому почти всегда следует отдавать предпочтение.
  • Реализация собственного средства сопоставления намерений: наиболее гибкий вариант. Более подробную информацию можно найти в разделе «Написание пользовательских сопоставлений» руководства Hamcrest .

Espresso-Intents предлагает методы intended() и intending() для проверки намерений и заглушки соответственно. Оба принимают в качестве аргумента объект Hamcrest Matcher<Intent> .

В следующем фрагменте кода показана проверка намерения, в которой используются существующие средства сопоставления намерений, соответствующие исходящему намерению, запускающему браузер:

Котлин

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 записывает все намерения, которые пытаются запустить действия из тестируемого приложения. Используя метод intended() , который похож на Mockito.verify() , вы можете утверждать, что данное намерение было замечено. Однако Espresso-Intents не блокирует ответы на намерения, если вы явно не настроите его для этого.

Следующий фрагмент кода представляет собой пример теста, который проверяет, но не блокирует ответы, исходящее намерение, запускающее внешнее «телефонное» действие:

Котлин

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

Заглушка

Используя метод intending() , который похож на Mockito.when() , вы можете предоставить ответ-заглушку для действий, которые запускаются с помощью startActivityForResult() . Это особенно полезно для внешних действий, поскольку вы не можете манипулировать пользовательским интерфейсом внешнего действия или контролировать ActivityResult , возвращаемый тестируемому действию.

В следующих фрагментах кода реализован пример теста activityResult_DisplaysContactsPhoneNumber() , который проверяет, что когда пользователь запускает действие «контакт» в тестируемом приложении, отображается номер контактного телефона:

  1. Создайте результат, который будет возвращаться при запуске определенного действия. Пример теста перехватывает все намерения, отправленные «контактам», и заглушает их ответы с действительным ActivityResult , используя код результата RESULT_OK

    Котлин

    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 предоставить объект-заглушку результата в ответ на все вызовы намерения «контакты»:

    Котлин

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

    Ява

    intending(toPackage("com.android.contacts")).respondWith(result);
    
  3. Убедитесь, что действие, использованное для запуска действия, дает ожидаемый результат-заглушку. В данном случае пример теста проверяет, что номер телефона «123-345-6789» возвращается и отображается при запуске «активности контактов»:

    Котлин

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

Котлин

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

Дополнительные ресурсы

Для получения дополнительной информации об использовании Espresso-Intents в тестах Android обратитесь к следующим ресурсам.

Образцы

  • IntentsBasicSample : базовое использование метода intended() и intending() .
  • IntentsAdvancedSample : имитирует получение пользователем растрового изображения с помощью камеры.