在 Espresso 中,指定要使用当前可见的 AdapterView

Posted

技术标签:

【中文标题】在 Espresso 中,指定要使用当前可见的 AdapterView【英文标题】:In Espresso, specify that you want to work with the current visible AdapterView 【发布时间】:2015-02-27 09:44:07 【问题描述】:

在一个活动中,我有一个 ViewPager 带有 2 个选项卡:“全部”和“已过滤”。 两个页面使用相同的Fragment 来显示数据,不同之处在于“已过滤”页面按某些条件过滤数据。

我想点击“全部”页面中的一个项目(可能也存在于“已过滤”页面中),如果我这样做:

onData(transactionWithId(960L)).perform(click());

作为回应,我得到:

AmbiguousViewMatcherException: '可从类中赋值:类 android.widget.AdapterView' 匹配层次结构中的多个视图

然后我尝试通过指定一个附加约束来优化我的描述,我正在寻找一个可见的项目:

onData(allOf(transactionWithId(960L), isDisplayed())).perform(click());

我也遇到了同样的错误。

然后我想以某种方式指定,我正在“所有”选项卡中寻找我的项目(虽然不确定这是否正确):

onData(allOf(
      transactionWithId(960L), 
      withParent(withText("ALL")))
   ).perform(click());

但同样的错误。

然后我尝试指定我正在寻找当前在我面前的AdapterView

onData(allOf(
       is(instanceOf(Transaction.class)), 
       transactionWithId(960L))
   ).inAdapterView(allOf(
            isAssignableFrom(AdapterView.class),
            isDisplayed())
          ).perform(click());

我得到了:

PerformException:在视图 '(是 可从类分配:类 android.widget.AdapterView 并且是 在屏幕上显示给用户)'。

请注意,我可以单击带有单个 ListViewActivity 中显示的项目,我面临的挑战是当我有一个带有多个选项卡的 ViewPager 时,使用一个 Fragment 来显示数据。 将不胜感激。

【问题讨论】:

【参考方案1】:

您的方法应该有效,我创建了一个最小的工作示例here。

问题的要点是区分两个适配器视图。另一种方法是用tags 明确标记它们。然后我们可以在特定标签上使用自定义Matcher 来限制DataInterationinAdapterView()。完整代码还是here,我引用重点:

在适配器视图中:

boolean isFiltered = ...
AdapterView av = ...
av.setTag(isFiltered);

在测试中:

@Test
public void testClickOnSecondItemInAllTab() 
    onData(instanceOf(String.class)).inAdapterView(withTag(false)) //
                                    .atPosition(1)                 //
                                    .perform(click());

以及标签上的自定义视图匹配器:

static Matcher<View> withTag(final Object tag) 
    return new TypeSafeMatcher<View>() 

        @Override
        public void describeTo(final Description description) 
            description.appendText("has tag equals to: " + tag);
        

        @Override
        protected boolean matchesSafely(final View view) 
            Object viewTag = view.getTag();
            if (viewTag == null) 
                return tag == null;
            

            return viewTag.equals(tag);
        
    ;

【讨论】:

以上是关于在 Espresso 中,指定要使用当前可见的 AdapterView的主要内容,如果未能解决你的问题,请参考以下文章

Espresso - 如何匹配 ActionBar 的可见性?

使用Espresso Test Recorder编写Android测试

如何在 Espresso 中重新运行失败的测试? - 头脑风暴

java 使用Espresso进行测试时要使用的改装API包装器

Espresso - 使用异步加载的数据断言 TextView

Android 自动化测试 Espresso篇:异步代码测试