2015年3月1日日曜日

EspressoでToast表示のチェックをする

公式ページにアプリケーションLayer以外のチェック方法が載っています。
Using inRoot to target non-default windows
https://code.google.com/p/android-test-kit/wiki/EspressoSamples#Using_inRoot_to_target_non-default_windows

1
2
3
onView(withText("South China Sea"))
  .inRoot(withDecorView(not(is(getActivity().getWindow().getDecorView()))))
  .perform(click());

上記の方法でもToast表示のチェックは行えますが、「non-default windows」であってToastの指定ではありません。
ということで、自作してしまいましょう。

ToastはWindowManager.LayoutParams.TYPE_TOASTというパラメータを持っています。
これは表示するLayerを指定するものです。
次はToast Layerを指定するMatcherのサンプルプログラムです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
 * Matcher that is Toast window.
 */
public static Matcher<Root> isToast() {
    return new 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) {
                    // 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;
        }
    };
}

EspressoのViewMatchersモジュールを自作する

EspressoのViewMatchersクラスには、たくさんの判定モジュールが用意されています。
ただ、JUnit作成時に「こんなチェックをしたいのに、標準で用意されていない」こともあります。
このような場合、自作するしかありません。

次のような作業が必要です。
  1. BoundedMatcherを実装したオブジェクトを戻り値とするモジュールを作成
  2. マッチしているかどうか判定するモジュール、matchesSafelyをオーバーライドして判定ロジックを作成
  3. 何を判定するMatcherなのかを記述するdescribeToをオーバーライドして実装

Espressoのソースが公開されていますので、参考になります。
ViewMatchersクラス:https://code.google.com/p/android-test-kit/source/browse/espresso/lib/src/main/java/com/google/android/apps/common/testing/ui/espresso/matcher/ViewMatchers.java

次はTextViewのColorが一致しているかどうか判定するMatcherのサンプルプログラムです。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public static Matcher<view> withTextColor(final int resourceId) {
 
        return new BoundedMatcher<view textview="">(TextView.class) {
            private int expectedColor = -1;
 
            private String resourceName;
 
 
            @Override
            protected boolean matchesSafely(TextView textView) {
                if (expectedColor == -1) {
                    try {
                        expectedColor = textView.getResources().getColor(resourceId);
                        resourceName = textView.getResources().getResourceEntryName(resourceId);
                    } catch (Resources.NotFoundException ignored) {
                        // view could be from a context unaware of the resource id.
                    }
                }
 
                if (expectedColor != -1) {
                    return (expectedColor == textView.getCurrentTextColor());
                } else {
                    return false;
                }
            }
 
            @Override
            public void describeTo(Description description) {
                description.appendText("with color from resource id: ");
                description.appendValue(resourceId);
                if (null != resourceName) {
                    description.appendText("[");
                    description.appendText(resourceName);
                    description.appendText("]");
                }
                if (-1 != expectedColor) {
                    description.appendText(" value: ");
                    description.appendText(String.valueOf(expectedColor));
                }
            }
        };
    }