我有一个RecyclerView(R.id.recyclerView),其中每一行都有一个图像(R.id.row_image)和一个TextView。我想点击第一行的图片 我尝试过使用onData(..),但它似乎无法正常工作。
答案 0 :(得分:73)
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'
}
答案 1 :(得分:21)
只是添加Gabor的答案(这是自Espresso 2.0以来的正确和完整答案)。
使用espresso-contrib
和RecyclerView
时,您可能会遇到问题(请参阅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答案的评论,因为我还没有权利发表评论)
答案 2 :(得分:15)
Espresso 2.0已发布,the changelog包含以下内容:
新功能
- 浓咖啡的contrib
- RecyclerViewActions:处理与RecyclerViews的交互
我还没有自己测试过这个问题,但Thomas Keller posted this在G +上有一个简短的解释和一个带有必要视图匹配的Gist的链接。
由于新
RecyclerView
API继承自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")));
答案 3 :(得分:5)
您应该使用自定义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));
}
}
答案 4 :(得分:2)
您无需添加&#34; testing-support-lib&#34;,也不会添加&#34; espresso:espresso-core&#34;。当&#34; espresso:espresso-contrib&#34;已添加。
<强> 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()));
答案 5 :(得分:2)
我找到了两种方法:
onView(allOf(withId(R.id.place_description),withText("what"))).perform(click());
`
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());
答案 6 :(得分:2)
与上述相同的答案,但由于需要提供Viewholder类型而做了一些小的修改
使用RecyclerViewActions
fun tapOnRecyclerView(@IdRes resId: Int , position: Int) = onView(withId(resId))
.perform(actionOnItemAtPosition<RecyclerView.ViewHolder>(position, click()));
并将此库包含在您的项目中,请使用
androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"
首选使用此link
中的最新浓缩咖啡答案 7 :(得分:1)
我关注了@ Gabor的回答但是当我收录了这些库时,我达到了dex限制!
所以,我删除了这些库,添加了这个getInstrumentation().waitForIdleSync();
,然后只调用了onView(withId...))...
完美无缺。
在您的情况下,您将拥有多个具有相同ID的图像视图,因此您必须弄清楚如何选择特定列表项。
答案 8 :(得分:1)
当我发布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
项中的任何元素。
要澄清的另一件事是检查可见性(subjectTextView.getVisibility() == View.VISIBLE)
。我们需要拥有它,因为有时RecyclerView
中的其他视图可能具有相同的主题,但它与View.GONE
相同。这样我们就可以避免我们的自定义匹配器的多个匹配项和仅实现显示我们主题的目标项。
答案 9 :(得分:0)
使用此代码,您可以滚动回收器视图以找到带有文本的商品并对其执行点击或其他操作。
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.3.0'
@Test
public void scrollRecyclerViewAndClick() {
onView(withId(R.id.recycler_view)).
perform(RecyclerViewActions.
actionOnItem(withText("specific string"), click()));
}