检查是否用浓缩咖啡显示对话框

我正在尝试用新的 机器人测试工具包(浓缩咖啡)编写一些测试。但是我找不到任何关于 怎么做的信息,检查是否显示了一个对话框并对其执行了一些操作(比如点击正面和负面按钮等)。请注意,对话框也可以由 WebView显示,而不是由应用程序自己显示。

我只需要一个链接,或者一些基本的示例代码:

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

谢谢你的建议!

68982 次浏览
  1. To verify if dialog appears you can simply check if View with a text that present inside the dialog is shown:

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

    or, based on text with id

    onView(withId(R.id.myDialogTextId)).check(matches(allOf(withText(myDialogText), isDisplayed()));
    
  2. To click on dialogs button do this (button1 - OK, button2 - Cancel):

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

    UPDATE

  3. I think is possible since Espresso has multi window support.
  4. Not sure about clicking outside the custom dialog view but for checking if it is displaying or not you have to create your custom matcher and check inside it.

I currently use this and it seems to work fine.

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

To answer question 4, which the accepted answer does not, I modified the following code, which I found here on Stack Overflow (link) for testing whether a Toast was displayed.

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

The id passed in is the id of a View currently displayed in your dialog. You could also write the method like so:

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

And now it's looking for a View containing a particular text string.

Use it like so:

getRootView(getActivity(), R.id.text_id).perform(click());

The button Ids R.id.button1 and R.id.button2 are not going to be same across devices. The Ids may change with the OS versions.

The correct way to achieve this is to use UIAutomator. Include UIAutomator dependency in your build.gradle

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

and use

// 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();
}

If you have an AlertDialog like that:

enter image description here

You can check if the components are displayed:

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

and perform an action:

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

Just in case anyone stumbles across this question like I did. All the answers will only work for dialogs WITH dialog buttons. Do not try and use this for progress dialogs without user interaction. Espresso keeps waiting for the app to enter an idle state. As long as the progress dialog is visible the app is not idle.

If you don't want to check for a specific String in a dialog, you can use hasWindowFocus(), like this:

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

Sources: