我现在在我的功能测试中工作,其中一个我必须测试没有显示Toast消息。考虑到这是我用来检查是否显示toast消息的代码(此代码有效):
onView(withText(R.string.my_toast_message))
.inRoot(withDecorView(not(getActivity().getWindow().getDecorView())))
.check(matches(isDisplayed()));
在下面你可以找到我用来检查没有显示toast消息的代码(它们都不起作用):
方法一:
onView(withText(R.string.error_invalid_login))
.inRoot(withDecorView(not(getActivity().getWindow().getDecorView())))
.check(matches(not(isDisplayed())));
方法二:
onView(withText(R.string.error_invalid_login))
.inRoot(withDecorView(not(getActivity().getWindow().getDecorView())))
.check(doesNotExist());
关于如何检查未显示Toast消息的任何想法将非常感激:)
答案 0 :(得分:4)
在espresso中测试吐司消息的最佳方法是使用自定义匹配器:
public class ToastMatcher extends TypeSafeMatcher<Root> {
@Override public void describeTo(Description description) {
description.appendText("is toast");
}
@Override public boolean matchesSafely(Root root) {
int type = root.getWindowLayoutParams().get().type;
if ((type == WindowManager.LayoutParams.TYPE_TOAST)) {
IBinder windowToken = root.getDecorView().getWindowToken();
IBinder appToken = root.getDecorView().getApplicationWindowToken();
if (windowToken == appToken) {
//means this window isn't contained by any other windows.
}
}
return false;
}
}
您可以在测试用例中使用:
测试是否显示Toast消息
onView(withText(R.string.message)).inRoot(new ToastMatcher())
.check(matches(isDisplayed()));
测试是否未显示Toast消息
onView(withText(R.string.message)).inRoot(new ToastMatcher())
.check(matches(not(isDisplayed())));
测试ID Toast包含特定的短信
onView(withText(R.string.message)).inRoot(new ToastMatcher())
.check(matches(withText("Invalid Name"));
我从我的博客中复制了这个答案 - http://qaautomated.blogspot.in/2016/01/how-to-test-toast-message-using-espresso.html
答案 1 :(得分:3)
当吐司不存在时,需要捕获该情况,其中抛出NoMatchingRootException
。下面显示了捕捉它的“Espresso方式”。
public static Matcher<Root> isToast() {
return new WindowManagerLayoutParamTypeMatcher("is toast", WindowManager.LayoutParams.TYPE_TOAST);
}
public static void assertNoToastIsDisplayed() {
onView(isRoot())
.inRoot(isToast())
.withFailureHandler(new PassMissingRoot())
.check(matches(not(anything("toast root existed"))))
;
}
使用上述内容的快速(自我)测试:
@Test public void testToastMessage() {
Toast toast = createToast("Hello Toast!");
assertNoToastIsDisplayed();
toast.show();
onView(withId(android.R.id.message))
.inRoot(isToast())
.check(matches(withText(containsStringIgnoringCase("hello"))));
toast.cancel();
assertNoToastIsDisplayed();
}
private Toast createToast(final String message) {
final AtomicReference<Toast> toast = new AtomicReference<>();
InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
@SuppressLint("ShowToast") // will be shown later
@Override public void run() {
toast.set(Toast.makeText(InstrumentationRegistry.getContext(), message, Toast.LENGTH_LONG));
}
});
return toast.get();
}
神奇的可重用帮助程序类:
public class PassMissingRoot implements FailureHandler {
private final FailureHandler defaultHandler
= new DefaultFailureHandler(InstrumentationRegistry.getTargetContext());
@Override public void handle(Throwable error, Matcher<View> viewMatcher) {
if (!(error instanceof NoMatchingRootException)) {
defaultHandler.handle(error, viewMatcher);
}
}
}
public class WindowManagerLayoutParamTypeMatcher extends TypeSafeMatcher<Root> {
private final String description;
private final int type;
private final boolean expectedWindowTokenMatch;
public WindowManagerLayoutParamTypeMatcher(String description, int type) {
this(description, type, true);
}
public WindowManagerLayoutParamTypeMatcher(String description, int type, boolean expectedWindowTokenMatch) {
this.description = description;
this.type = type;
this.expectedWindowTokenMatch = expectedWindowTokenMatch;
}
@Override public void describeTo(Description description) {
description.appendText(this.description);
}
@Override public boolean matchesSafely(Root root) {
if (type == root.getWindowLayoutParams().get().type) {
IBinder windowToken = root.getDecorView().getWindowToken();
IBinder appToken = root.getDecorView().getApplicationWindowToken();
if (windowToken == appToken == expectedWindowTokenMatch) {
// windowToken == appToken means this window isn't contained by any other windows.
// if it was a window for an activity, it would have TYPE_BASE_APPLICATION.
return true;
}
}
return false;
}
}
答案 2 :(得分:2)
这有效
boolean exceptionCaptured = false;
try {
onView(withText(R.string.error_invalid_login))
.inRoot(withDecorView(not(is(getActivity().getWindow().getDecorView()))))
.check(doesNotExist());
}catch (NoMatchingRootException e){
exceptionCaptured = true;
}finally {
assertTrue(exceptionCaptured);
}
答案 3 :(得分:1)
例如,如果您不仅有烤面包,而且还有PopupWindow
,似乎很难用浓缩咖啡进行这种简单的检查。
对于这种情况,建议只是放弃这里的浓缩咖啡,并使用UiAutomator
进行断言
val device: UiDevice
get() = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
fun assertPopupIsNotDisplayed() {
device.waitForIdle()
assertFalse(device.hasObject(By.text(yourText))))
}
fun assertPopupIsDisplayed() {
device.waitForIdle()
assertTrue(device.hasObject(By.text(yourText))))
}
答案 4 :(得分:0)
我知道它已经很晚了但可能会对其他人有所帮助。
onView(withText("Test")).inRoot(withDecorView(not(mActivityRule.getActivity().getWindow().getDecorView())))
.check(doesNotExist());
答案 5 :(得分:0)
喜欢@anuja jain的回答,但是如果你得到NoMatchingRootException
,你可以注释if ((type == WindowManager.LayoutParams.TYPE_TOAST))
检查并将return true;
行添加到内部if块。
答案 6 :(得分:0)
尝试以下解决方案
onView(withId(android.R.id.message))
.inRoot(withDecorView(not(is(mRule.getActivity().getWindow().getDecorView()))))
.check(matches(withText("Some message")));
答案 7 :(得分:-1)
您可以查看源代码here并创建自己的视图匹配器,完全相反。