在棉花糖中检测吐司

时间:2016-01-28 10:31:18

标签: android coded-ui-tests android-testing android-espresso ui-testing

我正在用浓缩咖啡写一些ui测试,我正试图断言祝酒词。我遇到的问题是我的代码在Lollipop上运行但在marshmallow上失败了,我无法理解为什么。

我的代码基本上是打开对话框,填写电子邮件并单击按钮。这应该是一个吐司,它确实(我在设备上通过目视检查确认),但我的测试未能检测到吐司。

为此,我为toasts创建了一个自定义匹配器类:

import android.os.IBinder;
import android.support.test.espresso.Root;
import android.view.WindowManager;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

import static com.google.android.exoplayer.util.Assertions.checkArgument;
import static com.google.android.exoplayer.util.Assertions.checkNotNull;
import static org.hamcrest.CoreMatchers.equalTo;

public class ToastMatcher{

    public static Matcher<Root> withToastText(String toastText) {
        // use preconditions to fail fast when a test is creating an invalid matcher.
        checkArgument(!(toastText.equals(null)));
        return withToastText(equalTo(toastText));
    }

    public static Matcher<Root> withToastText(final Matcher<String> matcherText) {

        // use preconditions to fail fast when a test is creating an invalid matcher.
        checkNotNull(matcherText);
        return new TypeSafeMatcher<Root>() {

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

        };
    }
}

至于我的测试用例

@Test
public void success() {
    String successMessage = mActivityRule.getActivity().getResources().getString(R.string.info_recover_instructions);
    String ok = mActivityRule.getActivity().getResources().getString(android.R.string.ok);
    // Click forgot button
    onView(withId(R.id.lg_forgot)).perform(click());
    // Fill email
    onView(withClassName(endsWith("EditText"))).perform(typeText(USERNAME));
    // Click OK button
    onView(withText(ok))
            .check(matches(isEnabled()))
            .perform(click());
    // Assert Toast
    onView(withText(successMessage)).inRoot(ToastMatcher.withToastText(successMessage)).check(matches(isDisplayed()));
}

正如我之前所说,这在Lollipop上运行得很好,但在Marshmallow上,它给了我以下错误:

android.support.test.espresso.NoMatchingRootException: Matcher 'is toast' did not match any of the following roots: [Root{application-window-token=android.view.ViewRootImpl$W@a66b932, window-token=android.view.ViewRootImpl$W@a66b932, has-window-focus=true, layout-params-type=2, layout-params-string=WM.LayoutParams{(0,0)(wrapxwrap) gr=#11 sim=#20 ty=2 fl=#1820002 fmt=-3 wanim=0x103045c needsMenuKey=2}, decor-view-string=DecorView{id=-1, visibility=VISIBLE, width=1026, height=483, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}}, Root{application-window-token=android.view.ViewRootImpl$W@8d64683, window-token=android.view.ViewRootImpl$W@8d64683, has-window-focus=false, layout-params-type=2, layout-params-string=WM.LayoutParams{(0,0)(wrapxwrap) gr=#11 sim=#20 ty=2 fl=#1800002 fmt=-3 wanim=0x103045c needsMenuKey=2}, decor-view-string=DecorView{id=-1, visibility=VISIBLE, width=1026, height=598, has-focus=true, has-focusable=true, has-window-focus=false, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=1}}, Root{application-window-token=android.view.ViewRootImpl$W@90a2000, window-token=android.view.ViewRootImpl$W@90a2000, has-window-focus=false, layout-params-type=1, layout-params-string=WM.LayoutParams{(0,0)(fillxfill) ty=1 fl=#81810100 wanim=0x103045b needsMenuKey=2}, decor-view-string=DecorView{id=-1, visibility=VISIBLE, width=1080, height=1920, has-focus=true, has-focusable=true, has-window-focus=false, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3}}]

我做错了什么或者应该在android Marshmallow上做不同的事情?

1 个答案:

答案 0 :(得分:1)

试一试。不确定它是否适用于Marshmallow:

onView(withText(R.string.toastText))    
    .inRoot(withDecorView(not(is(mActivityRule.getActivity().getWindow().getDecorView()))))
        .check(matches(isDisplayed()));