98

我正在尝试使用新的android-test-kit (Espresso)编写一些测试。但是我找不到有关如何检查是否显示对话框并对其执行一些操作的任何信息(例如单击正面和负面按钮等)。请注意,对话框也可能由 a 显示WebView,而不是由它自己的应用程序显示。

任何帮助,将不胜感激。我只需要一个链接或一些基本示例代码:

  1. 检查是否出现对话框
  2. 执行单击对话框按钮
  3. 与对话框的内部视图交互(如果它是自定义视图)
  4. 在对话框外单击预制件,并检查它是否正在显示(例如,如果setCancelable(false)在对话框构建器上调用并且我们想要检查它)

谢谢指教!

4

7 回答 7

137
  1. 要验证是否出现对话框,您只需检查是否显示了带有对话框内文本的视图:

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

    或者,基于带有 id 的文本

    onView(withId(R.id.myDialogTextId)).check(matches(allOf(withText(myDialogText), isDisplayed()));
    
  2. 要单击对话框按钮,请执行此操作(按钮 1 - 确定,按钮 2 - 取消):

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

    更新

  3. 我认为这是可能的,因为 Espresso支持多窗口
  4. 不确定是否在自定义对话框视图之外单击,但要检查它是否正在显示,您必须创建自定义匹配器并在其中检查。
于 2014-01-10T14:28:05.433 回答
77

我目前使用它,它似乎工作正常。

onView(withText(R.string.my_title))
    .inRoot(isDialog()) // <---
    .check(matches(isDisplayed()));
于 2015-04-23T09:56:44.097 回答
29

如果您有这样的 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());
于 2016-07-04T18:08:47.803 回答
3

为了回答接受的答案没有的问题 4,我修改了以下代码,我在 Stack Overflow (链接) 上找到了这些代码,用于测试是否显示了 Toast。

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

传入的idView当前显示在对话框中的 id。你也可以这样写方法:

@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());
于 2015-12-08T23:07:54.783 回答
3

按钮 ID R.id.button1 和 R.id.button2 在设备之间不会相同。ID 可能会随操作系统版本而变化。

实现这一点的正确方法是使用 UIAutomator。在 build.gradle 中包含 UIAutomator 依赖项

// 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();
}
于 2015-12-25T18:04:12.337 回答
3

以防万一有人像我一样偶然发现这个问题。所有答案仅适用于带有对话框按钮的对话框。不要尝试在没有用户交互的情况下将其用于进度对话框。Espresso 一直在等待应用程序进入空闲状态。只要进度对话框可见,应用程序就不会空闲。

于 2017-09-26T11:33:20.560 回答
1

如果您不想在对话框中检查特定字符串,可以使用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();

资料来源:

于 2021-09-24T13:03:46.617 回答