Проверьте, отображается ли диалоговое окно с Espresso

86

Пытаюсь написать тесты с новым тестовым набором для Android (Espresso) . Но я не могу найти никакой информации о том, как проверить, отображается ли диалоговое окно, и выполнить с ним какие-либо действия (например, щелкнуть положительные и отрицательные кнопки и т. Д.). Обратите внимание, что диалоговое окно также может отображаться, а WebViewне самим приложением.

Любая помощь будет оценена. Мне просто нужна ссылка или пример кода для основ:

  1. Проверьте, появляется ли диалоговое окно
  2. Выполнять щелчки по кнопкам диалога
  3. Взаимодействовать с внутренним видом диалога (если это настраиваемый вид)
  4. Preform щелкает за пределами диалогового окна и проверяет, отображается ли он или нет (например, если setCancelable(false)был вызван в построителе диалогов, и мы хотим это проверить)

Спасибо за совет!

Серж Лотутовичи
источник
Любые отзывы о моем ответе ниже ??
denys

Ответы:

123
  1. Чтобы проверить, появляется ли диалоговое окно, вы можете просто проверить, отображается ли Просмотр с текстом, присутствующим внутри диалогового окна:

    onView(withText("dialogText")).check(matches(isDisplayed()));
    

    или, на основе текста с идентификатором

    onView(withId(R.id.myDialogTextId)).check(matches(allOf(withText(myDialogText), isDisplayed()));
    
  2. Чтобы щелкнуть по кнопке диалогов, сделайте следующее (button1 - ОК, button2 - Отмена):

    onView(withId(android.R.id.button1)).perform(click());
    

    ОБНОВИТЬ

  3. Я думаю, что это возможно, так как Espresso поддерживает многооконный режим .
  4. Не уверен, что щелкаю за пределами настраиваемого диалогового окна, но для проверки, отображается он или нет, вам нужно создать свой настраиваемый сопоставитель и проверить его внутри.
Денис
источник
3
Шаг 1 не сработал для меня в ProgressDialog. Просто пытаюсь проверить заголовок и сообщение диалога
Тим Боланд
1
Что такое с эспрессо и статическим импортом? Из каких классов берутся эти методы? Почему вы используете статический импорт в ответе на переполнение стека?
2
@jvrodrigues каждый учебник Espresso использует статический импорт. Я предлагаю вам просто привыкнуть к этому (хотя я понимаю разочарование). Это помогает: google.github.io/android-testing-support-library/docs
AutonomousApps
Для шага 4 вместо щелчка за пределами диалогового окна вы можете вызвать "pressBack ();" который закрывает диалог. это эквивалент использования аппаратной кнопки возврата.
Итан
Проект @denys был перемещен. похоже ссылка мертвая.
Neon Warge
67

В настоящее время я использую это, и, похоже, он работает нормально.

onView(withText(R.string.my_title))
    .inRoot(isDialog()) // <---
    .check(matches(isDisplayed()));
кирувка
источник
27

Если у вас есть такой AlertDialog:

введите описание изображения здесь

Вы можете проверить, отображаются ли компоненты:

int titleId = mActivityTestRule.getActivity().getResources()
        .getIdentifier( "alertTitle", "id", "android" );

onView(withId(titleId))
        .inRoot(isDialog())
        .check(matches(withText(R.string.my_title)))
        .check(matches(isDisplayed()));

onView(withId(android.R.id.text1))
        .inRoot(isDialog())
        .check(matches(withText(R.string.my_message)))
        .check(matches(isDisplayed()));

onView(withId(android.R.id.button2))
        .inRoot(isDialog())
        .check(matches(withText(android.R.string.no)))
        .check(matches(isDisplayed()));

onView(withId(android.R.id.button3))
        .inRoot(isDialog())
        .check(matches(withText(android.R.string.yes)))
        .check(matches(isDisplayed()));

и выполните действие:

onView(withId(android.R.id.button3)).perform(click());
Луис Аугусто
источник
2
Текст в моем случае имел идентификатор, android.R.id.messageа заголовок имел скрытый идентификатор android.R.id.alertTitle.
Джейсон Робинсон,
2
Если вы используете AlertDialog (или DialogFragment), который поступает из библиотеки поддержки AppCompat, используйте это:int alertDialogTitleId = android.support.v7.appcompat.R.id.alertTitle;
Mr-IDE,
3

Чтобы ответить на вопрос 4, которого нет в принятом ответе, я изменил следующий код, который я нашел здесь в Stack Overflow ( ссылка ), чтобы проверить, отображается ли тост.

@NonNull
public static ViewInteraction getRootView(@NonNull Activity activity, @IdRes int id) {
    return onView(withId(id)).inRoot(withDecorView(not(is(activity.getWindow().getDecorView()))));
}

idПрошел в это идентификатор Viewотображается в данный момент в вашем диалоге. Вы также можете написать такой метод:

@NonNull
public static ViewInteraction getRootView(@NonNull Activity activity, @NonNull String text) {
    return onView(withText(text)).inRoot(withDecorView(not(is(activity.getWindow().getDecorView()))));
}

И теперь он ищет объект, Viewсодержащий конкретную текстовую строку.

Используйте это так:

getRootView(getActivity(), R.id.text_id).perform(click());
Автономные приложения
источник
3

Идентификаторы кнопок R.id.button1 и R.id.button2 не будут одинаковыми на разных устройствах. Идентификаторы могут меняться в зависимости от версии ОС.

Правильный способ добиться этого - использовать UIAutomator. Включите зависимость UIAutomator в свой build.gradle

// Set this dependency to build and run UI Automator tests
  androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'

и использовать

// Initialize UiDevice instance
UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());

// Search for correct button in the dialog.
UiObject button = uiDevice.findObject(new UiSelector().text("ButtonText"));
if (button.exists() && button.isEnabled()) {
    button.click();
}
JaydeepW
источник
1
На самом деле, android.R.id.button1, android.R.id.button2и android.R.id.button3для «позитив», «нейтральный» и «негативный», являются глобальные символы , которые могут быть использованы. Если вы выбираете кнопки с помощью их текста - что совершенно нормально - вам не нужен UIAutomator, но вы можете сделать то же самое с Espresso onView(withText("ButtonTest")).perform(click()).
Томас Келлер,
Я использовал это решение с тестовой платформой Robotium, и мне было легко выбирать кнопки диалогового окна Android OS. Сэкономил кучу времени. Спасибо, jaydeepw!
Ray
@ThomasKeller Раньше я использовал идентификаторы button1, button2, мои тесты ломались, когда я запускал их на различных устройствах. Показанный диалог является системным элементом управления. Не ваш контроль / пользовательский интерфейс. Для всего, что выходит за пределы вашего пользовательского интерфейса, рекомендуется использовать UIAutomator.
JaydeepW
Вот и все. Большое спасибо.
1lb3r,
3

На всякий случай, если кто-то наткнется на этот вопрос, как и я. Все ответы будут работать только для диалогов с кнопками диалога. Не пытайтесь использовать это для диалоговых окон прогресса без взаимодействия с пользователем. Espresso продолжает ждать, пока приложение перейдет в состояние ожидания. Пока отображается диалог выполнения, приложение не простаивает.

Диана Фарин
источник