LoginSignup
5
7

More than 5 years have passed since last update.

[Espresso] NavigationViewをNavigationViewActionsで操作してみようの話

Last updated at Posted at 2016-03-22

AndroidTestでNavigationView操作したいよね?

ちょっと前に静かにReleaseされていたEspresso 2.2.2にNavigationViewを操作するNavigationViewActionsというのが追加されていたのでそのお話。

NavigationViewの基本的な使い方は以下のQiitaにお任せするぜー。

"NavigationViewを使ってGoogle Play風のメニューを作る【Android Design Support Library】"
http://qiita.com/chuross/items/60af0aca3e1c3f946f09

DrawerLayoutとNavigationViewは仲良しこよし

まず、NavigationViewの各メニューの特徴として、それぞれのメニューが個別のidを持っているってこと。

「あーならそのid指定してどれ選択するか書いてあげればいいのねー」ってことになる。

ただNavigationViewは基本的にDrawerLayoutの子Viewとして追加して使うことが多いと思ってる。

DroidKaigiアプリのTop画面のレイアウトとか見るとまあわかると思う。以下のようにDrawerLayoutの子ViewとしてNavigationViewを使ってる。

github.com/konifar/droidkaigi2016/blob/master/app/src/main/res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="io.github.droidkaigi.confsched.activity.MainActivity">

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:openDrawer="start">

        ....

        <android.support.design.widget.NavigationView
            android:id="@+id/nav_view"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/nav_header"
            app:itemTextColor="@color/nav_view_colors"
            app:menu="@menu/drawer_menu"
            app:insetForeground="#4000"/>
    </android.support.v4.widget.DrawerLayout>
</layout>

何が言いたいのかというと、NavigationViewをNavigationViewActionsで操作するには、まずはDrawerLayoutをOpenしないとNavigationViewの各メニューがUI上表示されなくて操作できないってこと。

DrawerLayoutをOpenしないまま後ほど紹介するNavigationViewActionsを使うと以下のように
「Clickできないー(´・ω・`)」ってエラーが出ます。

android.support.test.espresso.PerformException: 
Error performing 'click on menu item with id' on view 'with id: 
io.github.droidkaigi.confsched.develop.debug:id/nav_view'.

NavigationViewActionsの使い方

ではでは、以上のことをふまえてDroidKaigiアプリのNavigationViewの各メニューを操作してAndroidTestでそれぞれの画面を表示してみた。

まずは、build.gradleのdependenciesにEspresso2.2.2とかもろもそ追加します。

雑にdependencies部分だけ抜き出し。ちなみに、使ってるsupport libによってバージョンが違うぞ!とか怒られるので、Espressoに含まれてるものはexcludeで抜いておくのがいいよ。

app/build.gradle
dependencies {
    compile "com.android.support:appcompat-v7:23.2.0"
    compile "com.android.support:design:23.2.0"

    androidTestCompile('com.android.support.test:runner:0.5') {
        exclude group: 'com.android.support', module: 'support-annotations'
    }
    androidTestCompile('com.android.support.test:rules:0.5') {
        exclude group: 'com.android.support', module: 'support-annotations'
    }
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2') {
        exclude group: 'com.android.support', module: 'support-annotations'
    }
    androidTestCompile('com.android.support.test.espresso:espresso-intents:2.2.2') {
        exclude group: 'com.android.support', module: 'support-annotations'
    }
    androidTestCompile ('com.android.support.test.espresso:espresso-contrib:2.2.2') {
        exclude group: 'com.android.support', module: 'support-annotations'
        exclude group: 'com.android.support', module: 'support-v4'
        exclude group: 'com.android.support', module: 'recyclerview-v7'
        exclude group: 'com.android.support', module: 'appcompat-v7'
        exclude group: 'com.android.support', module: 'design'
    }
}

テストコード側は以下のようにDrawerLayout Open -> NavigationViewActions.navigateTo(id)を繰り返して各メニューを開いていく。

Thread.sleepは開いたのをちゃんと目視するためにメニューが切り替わったらちょっと止めてるだけ。

MainActivityTest.java
@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

    @Rule
    public IntentsTestRule<MainActivity> activityRule = new IntentsTestRule<>(MainActivity.class);

    @Test
    public void test_navigation_view() throws InterruptedException {
        onView(withId(R.id.drawer)).perform(DrawerActions.open());
        onView(withId(R.id.nav_view)).perform(NavigationViewActions.navigateTo(R.id.nav_my_schedule));
        Thread.sleep(1500);

        onView(withId(R.id.drawer)).perform(DrawerActions.open());
        onView(withId(R.id.nav_view)).perform(NavigationViewActions.navigateTo(R.id.nav_map));
        Thread.sleep(1500);

        onView(withId(R.id.drawer)).perform(DrawerActions.open());
        onView(withId(R.id.nav_view)).perform(NavigationViewActions.navigateTo(R.id.nav_settings));
        Thread.sleep(1500);

        onView(withId(R.id.drawer)).perform(DrawerActions.open());
        onView(withId(R.id.nav_view)).perform(NavigationViewActions.navigateTo(R.id.nav_sponsors));
        Thread.sleep(1500);

        onView(withId(R.id.drawer)).perform(DrawerActions.open());
        onView(withId(R.id.nav_view)).perform(NavigationViewActions.navigateTo(R.id.nav_about));
        Thread.sleep(1500);

        onView(withId(R.id.drawer)).perform(DrawerActions.open());
        onView(withId(R.id.nav_view)).perform(NavigationViewActions.navigateTo(R.id.nav_all_sessions));
        Thread.sleep(1500);
    }
}

基本は以下の二行です。

DrawerActions.openでDrawerLayoutを開くとUI上にNavigationViewの各メニューが表示されるので、NavigationViewActions.navigateTo(id)で選択したいメニューのidを引数に渡します。

onView(withId(R.id.drawer)).perform(DrawerActions.open());
onView(withId(R.id.nav_view)).perform(NavigationViewActions.navigateTo(R.id.nav_all_sessions));

ちょっと注意して欲しいのはDrawerLayoutをOpenする方法はDrawerActions.openを使いのがよいです。

昔はDrawerActions.openDrawerってものがあったんだけど、これはDeprecatedになってます。

// Good!!
onView(withId(R.id.drawer)).perform(DrawerActions.open()); 

// Deprecated!! NO!!
DrawerActions.openDrawer(R.id.drawer);

端末上で動かすと以下のような感じでちゃんとDrawerLayoutをOpenしてNavigationViewの各メニューを選択して画面が切り替わってます。

test.gif

NavigationViewActionsの情報

以上のような感じでNavigationViewをNavigationViewActionsで操作できたわけですが、そもそもこれいつ追加されたんやー!!って話なんですよ。

んで、これを見つけたきっかけはちらっと以下のAndroid Testing Support LibraryのRelease Notesを見たのがきっかけ。

Espresso 2.2.2, Runner/Rules 0.5 (2016-02-22, silent release)
New Features

  • espresso
    • Issue 194253: Add support for NavigationView in android support design library

ほむほむ。Espresso 2.2.2でNavigationViewの操作をSupportしたよ!!って感じ。

んじゃ、NavigationViewを操作するクラスなによ??って話で、EspressoのJavadoc見てみた。

「Classes見れば追加されてるはずだよねー♪」

スクリーンショット 2016-03-22 18.25.27.png

...(´・ω・`)

お分かりいただけるだろうか

なんとJavadocにNavigationViewActionsが追加されていない。

どうやらEspresso 2.2.2, Runner/Rules 0.5 のRelease内容がJavadocに反映されていない。

Silent Releaseだから??それとも別に最新のJavadocあるの??知っている人いたら教えてほしい...。

ローカルのjarとか見ればNavigationViewActionsの実装見れるけど面倒は人はNavigationViewActionsの中身をGistに移したので参考までに。

ちなみに、NavigationViewActionsの実装は元々android-testingのcustom actionとして実装されていたものをほぼほぼそのまま採用したっぽい実装になっている。

NavigationViewActions Sample

NavigationViewActionsを使った雑なSampleを作ったみたので手元で動かしたい人はこれで試してみてください。

まとめ

NavigationViewが簡単に操作できるようになってめでたしめでたしでした。

5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7