Проверьте, отображается ли диалог с эспрессо

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

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

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

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

7 ответов

Решение
  1. Чтобы проверить, появляется ли диалоговое окно, вы можете просто проверить, отображается ли View с текстом, который присутствует внутри диалога:

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

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

    onView(withId(R.id.myDialogTextId)).check(matches(allOf(withText(myDialogText), isDisplayed()));
    
  2. Чтобы нажать кнопку диалога, сделайте это (button1 - OK, button2 - Cancel):

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

    ОБНОВИТЬ

  3. Я думаю, что это возможно, так как Espresso имеет многооконную поддержку.
  4. Не уверен, что нажмете за пределами пользовательского диалогового окна, но для проверки, отображается ли он или нет, вам нужно создать свой собственный сопоставитель и проверить внутри него.

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

onView(withText(R.string.my_title))
    .inRoot(isDialog()) // <---
    .check(matches(isDisplayed()));

Если у вас 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());

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

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

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

Если вы не хотите проверять конкретную строку в диалоговом окне, вы можете использовать hasWindowFocus(), нравится:

      // Kotlin, with ActivityScenarioRule
activityScenarioRule.scenario.onActivity { activity ->
   val dialogIsDisplayed = !activity.hasWindowFocus()
}

// Kotlin, with ActivityTestRule
val dialogIsDisplayed = !activityTestRule.activity.hasWindowFocus()


// Java 7, with ActivityScenarioRule
activityScenarioRule.getScenario().onActivity(new ActivityScenario.ActivityAction<MyActivity>() {
    @Override
    public void perform(MyActivity activity) {
        boolean dialogIsDisplayed = !activity.hasWindowFocus();
    }
});

// Java, with ActivityTestRule
boolean dialogIsDisplayed = !activityTestRule.getActivity().hasWindowFocus();

Источники:

Идентификаторы кнопок 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();
}
Другие вопросы по тегам