Espresso - 在列表视图中按文本点击

Posted

技术标签:

【中文标题】Espresso - 在列表视图中按文本点击【英文标题】:Espresso - Click by text in List view 【发布时间】:2014-04-09 14:34:05 【问题描述】:

我正在尝试使用 Espresso 在列表视图中单击文本。我知道他们有this guide,但我不知道如何通过查找文本来完成这项工作。这是我尝试过的

Espresso.onData(Matchers.allOf(Matchers.is(Matchers.instanceOf(ListView.class)), Matchers.hasToString(Matchers.startsWith("ASDF")))).perform(ViewActions.click());

正如预期的那样,这不起作用。该错误表示层次结构中没有视图。有谁知道如何选择字符串? (在这种情况下为"ASDF")提前致谢。

由于@haffax而更新

我收到错误:

com.google.android.apps.common.testing.ui.espresso.AmbiguousViewMatcherException: 'is assignable from class: class android.widget.AdapterView' 匹配层次结构中的多个视图。

第二个错误

使用此代码

onData(hasToString(startsWith("ASDF"))).inAdapterView(withContentDescription("MapList")).perform(click());

我收到此错误

com.google.android.apps.common.testing.ui.espresso.PerformException:在视图上执行“加载适配器数据”时出错,内容描述为“MapList”。

原因:java.lang.RuntimeException:找不到匹配的数据:asString(以“ASDF”开头的字符串)


解决方案

onData(anything()).inAdapterView(withContentDescription("desc")).atPosition(x).perform(click())

【问题讨论】:

这个异常的有趣之处在堆栈跟踪的下方。整个堆栈跟踪中应该有一个“Caused by:”部分。这描述了真正出了什么问题。请分享完整的堆栈跟踪以供分析。 @haffax,检查一下。那个字符串肯定在那里。 @haffax,但是,首先有一个线性布局。 这变得越来越复杂。那么,您实际上无法访问适应的类型,这是正确的吗? 如果您无权访问支持数据类型,那么您需要使用 onData(anything()).inAdapterView(...) 遍历该项目在 ListView 中的位置.atPosition(x).perform(click()) 点击列表中的第 x 个项目。 【参考方案1】:

问题是,您尝试将列表视图本身与instanceOf(ListView.class) 匹配作为onData() 的参数。 onData() 需要一个数据匹配器来匹配ListView 的适配数据,而不是ListView 本身,也不是Adapter.getView() 返回的View,而是实际数据。

如果你的生产代码中有这样的东西:

ListView listView = (ListView)findViewById(R.id.myListView);
ArrayAdapter<MyDataClass> adapter = getAdapterFromSomewhere();
listView.setAdapter(adapter);

那么 Espresso.onData() 的 Matcher 参数应该匹配 MyDataClass 的所需实例。 所以,这样的事情应该可以工作:

onData(hasToString(startsWith("ASDF"))).perform(click());

(您可以使用org.hamcrest.Matchers的方法使用另一个Matcher)

如果您的活动中有多个适配器视图,您可以使用视图匹配器调用 ViewMatchers.inAdapterView(),指定 AdapterView,如下所示:

onData(hasToString(startsWith("ASDF")))
    .inAdapterView(withId(R.id.myListView))
    .perform(click());

【讨论】:

答案扩展为包括层次结构中多个 AdapterViews 的解决方案。 我遇到了同样的错误,但**MATCHES**的错误更少 匹配的两个,似乎是一样的。我能看到的唯一区别是is=focused=false 好吧,您必须自己整理匹配项。有这么多具有​​相同 ID 的不同列表视图似乎很奇怪。你不能给你的列表视图不同的ID吗?或者这是因为在 ListFragments 中使用了?其他进一步区分的方法:为视图分配标签并使用 hasTag() 匹配器或使用 isDescendantOfA() 通过层次结构进行区分。 是的,我也觉得很奇怪。我没有编写应用程序,我只是测试它。但是,是的,你是对的,我不能给他们不同的 id,因为他们在 ListFragments 中。我会考虑添加一个标签。【参考方案2】:

如果适配器有自定义模型类,例如Item

public static Matcher<Object> withItemValue(final String value) 
        return new BoundedMatcher<Object, Item>(Item.class) 
            @Override
            public void describeTo(Description description) 
                description.appendText("has value " + value);
            

            @Override
            public boolean matchesSafely(Item item) 
                return item.getName().toUpperCase().equals(String.valueOf(value));
            
        ;
    

然后调用以下:

onData(withItemValue("DRINK1")).inAdapterView(withId(R.id.menu_item_grid)).perform(click());

【讨论】:

这在一个屏幕上对我有用,但在另一个屏幕上,Espresso 似乎滚动到该项目,但即使调用 perform(click()) 也不会单击该项目(用断点测试过)....这很奇怪【参考方案3】:
onData(hasEntry(equalTo(ListViewActivity.ROW_TEXT),is("List item: 25")))
        .onChildView(withId(R.id.rowTextView)).perform(click());

这对我来说最适合使用行文本数据..

【讨论】:

以上是关于Espresso - 在列表视图中按文本点击的主要内容,如果未能解决你的问题,请参考以下文章

Espresso 如何点击一个 ImageView 放置在 listview 的第一项?

Espresso 点击文本的特定单词

用于 viewpager 列表视图的 Espresso 2.0 AmbiguousViewMatcherException

在列表视图中按下项目时出错

Espresso 无法点击显示的视图

如何在列表视图中聚焦下一个编辑文本