web-dev-qa-db-ja.com

EspressoのRecyclerView内のアイテムをクリックする方法

各行に画像(R.id.row_image)とTextViewがあるRecyclerView(R.id.recyclerView)があります。最初の行の画像をクリックします。
onData(..)を使用しようとしましたが、機能していないようです。

36
Jacki

RecyclerViewActions を使用します

onView(withId(R.id.recyclerView))
    .perform(actionOnItemAtPosition(0, click()));

これをgradleスクリプトに含めます:

dependencies {
    androidTestCompile 'com.Android.support.test:testing-support-lib:0.1'
    androidTestCompile 'com.Android.support.test.espresso:espresso-core:2.0'
    androidTestCompile 'com.Android.support.test.espresso:espresso-contrib:2.0'
}
76
Gabor

Gaborの回答に追加するだけです(これはEspresso 2.0以降の正しい完全な回答です)。

espresso-contribおよびRecyclerViewsを使用しているときに問題が発生する場合があります( Android-test-kit ticket を参照)。

回避策は、上記のespresso-contrib依存関係Gaborにこの除外を追加することです。

androidTestCompile('com.Android.support.test.espresso:espresso-contrib:2.0') {
    exclude group: 'com.Android.support', module: 'appcompat'
    exclude group: 'com.Android.support', module: 'support-v4'
    exclude module: 'recyclerview-v7'
}

(これはまだコメントを投稿する権利がないため、Gaborの回答に対するコメントではなく回答です)

21
Sir4ur0n

編集:

Espresso 2.0がリリースされました。 変更ログ には以下が含まれます。

新機能

  • エスプレッソ-contrib
    • RecyclerViewActions:RecyclerViewsとの相互作用を処理します

古い答え

私はまだこれを自分でテストしていませんが、トーマス・ケラー 投稿済み G +で、簡単な説明と、必要なビューマッチャーを含むGistへのリンクがあります。

新しいRecyclerView AP​​IはViewGroupではなくAdapterViewから継承するため、EspressoのonData()を使用してこのコンポーネントを使用してレイアウトをテストすることはできません。

要旨へのリンク

完全を期すために、コードを添付します(注:私のものではありません!すべてのクレジットはThomas Kellerにあります)

ViewMatcher:

public class ViewMatchers {
    @SuppressWarnings("unchecked")
    public static Matcher<View> withRecyclerView(@IdRes int viewId) {
        return allOf(isAssignableFrom(RecyclerView.class), withId(viewId));
    }

    @SuppressWarnings("unchecked")
    public static ViewInteraction onRecyclerItemView(@IdRes int identifyingView, Matcher<View> identifyingMatcher, Matcher<View> childMatcher) {
        Matcher<View> itemView = allOf(withParent(withRecyclerView(R.id.start_grid)),
                withChild(allOf(withId(identifyingView), identifyingMatcher)));
        return Espresso.onView(allOf(isDescendantOfA(itemView), childMatcher));
    }
}

そしてサンプル使用法:

onRecyclerItemView(R.id.item_title, withText("Test"),  withId(R.id.item_content))
    .matches(check(withText("Test Content")));
16
aried3r

カスタムViewActionを使用する必要があります。

public void clickOnImageViewAtRow(int position) {
    onView(withId(R.id.recycler_view)).perform(RecyclerViewActions.actionOnItemAtPosition(position, new ClickOnImageView()));
}

public class ClickOnImageView implements ViewAction{
    ViewAction click = click();

    @Override
    public Matcher<View> getConstraints() {
        return click.getConstraints();
    }

    @Override
    public String getDescription() {
        return " click on custom image view";
    }

    @Override
    public void perform(UiController uiController, View view) {
        click.perform(uiController, view.findViewById(R.id.imageView));
    }
}
6
fede1608

「testing-support-lib」も「espresso:espresso-core」も追加する必要はありません。 「espresso:espresso-contrib」が追加されると、それらは推移的に追加されます。

build.grade

dependencies {
    androidTestCompile 'com.Android.support.test:runner:0.3'
    androidTestCompile 'com.Android.support.test:rules:0.3'
    androidTestCompile 'com.Android.support.test.espresso:espresso-contrib:2.2'
}

使用法

onView(withId(R.id.recyclerView)).perform(
            RecyclerViewActions.actionOnItemAtPosition(0, click()));
2

私は2つの方法を見つけました:

  1. RecyclerViewの各アイテムにID「R.id.description」のテキストビューがあると仮定します。これを実行して、特定の子に一致させることができます。

onView(allOf(withId(R.id.place_description),withText("what"))).perform(click());

  1. Android Codelabのテスト https://codelabs.developers.google.com/codelabs/Android-testing/# のチュートリアル

`

public Matcher<View> withItemText(final String itemText) {
        checkArgument(!TextUtils.isEmpty(itemText),"cannot be null");
        return new TypeSafeMatcher<View>() {
            @Override
            protected boolean matchesSafely(View item) {
                return allOf(isDescendantOfA(isAssignableFrom(RecyclerView.class)),withText(itemText)).matches(item);
            }

            @Override
            public void describeTo(Description description) {
                description.appendText("is descendant of a RecyclerView with text" + itemText);
            }
        };
    }

`

そして、これを行います:

onView(withItemText("what")).perform(click());
2
Luo Lei

私は@Gaborの答えに従いましたが、ライブラリを含めると、私はデックスの制限に達しました!

そのため、ライブラリを削除し、このgetInstrumentation().waitForIdleSync();を追加してからonView(withId...))...を呼び出しました

完全に動作します。

あなたの場合、同じIDを持つ複数の画像ビューがあるので、特定のリスト項目を選択する方法について何かを理解する必要があります。

1
vedant

here を投稿したように、カスタムRecyclerViewマッチャーを実装できます。 RecyclerViewがあり、各要素が一致する主題を持っていると仮定しましょう:

public static Matcher<RecyclerView.ViewHolder> withItemSubject(final String subject) {
    Checks.checkNotNull(subject);
    return new BoundedMatcher<RecyclerView.ViewHolder, MyCustomViewHolder>(
            MyCustomViewHolder.class) {

        @Override
        protected boolean matchesSafely(MyCustomViewHolder viewHolder) {
            TextView subjectTextView = (TextView)viewHolder.itemView.findViewById(R.id.subject_text_view_id);

            return ((subject.equals(subjectTextView.getText().toString())
                    && (subjectTextView.getVisibility() == View.VISIBLE)));
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("item with subject: " + subject);
        }
    };
}

そして使用法:

onView(withId(R.id.my_recycler_view_id)
    .perform(RecyclerViewActions.actionOnHolderItem(withItemSubject("My subject"), click()));

基本的に、あなたはあなたが望むものにマッチすることができます。この例では、サブジェクトTextViewを使用しましたが、RecyclerViewアイテム内の任意の要素を使用できます。

もう1つ明確にする必要があるのは、可視性の確認(subjectTextView.getVisibility() == View.VISIBLE)RecyclerView内の他のビューも同じ件名を持つことができますが、View.GONE。このようにして、カスタムマッチャーの複数の一致を回避し、実際に件名を表示するアイテムのみをターゲットにします。

1
denys