【问题标题】:Click on not fully visible imageButton with Espresso用 Espresso 点击不完全可见的 imageButton
【发布时间】:2015-05-04 06:26:01
【问题描述】:

我有一个自定义的 ImageButton 设计不完全可见,所以当我执行点击操作时,我收到此错误:

android.support.test.espresso.PerformException: Error performing 'single click' on view 'with id: test.com.myproject.app:id/navigationButtonProfile'.
Caused by: java.lang.RuntimeException: Action will not be performed because the target view does not match one or more of the following constraints:
at least 90 percent of the view's area is displayed to the user.
at android.support.test.espresso.ViewInteraction$1.run(ViewInteraction.java:138)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:157)
at android.app.ActivityThread.main(ActivityThread.java:5356)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
at dalvik.system.NativeStart.main(Native Method)

按钮的一小部分在屏幕之外(即在顶部被裁剪),可能 12% 的按钮在屏幕之外。这是设计使然,无法滚动或执行任何视图操作以使其可见。 有谁知道如何克服这个 90% 的限制?

解决方案: 我按照建议创建了自己的单击操作,并且效果很好。 我从Google Espresso复制了类,在这个方法中从90改成了75:

    @Override
    @SuppressWarnings("unchecked")
    public Matcher<View> getConstraints() {
        Matcher<View> standardConstraint = isDisplayingAtLeast(75);
        if (rollbackAction.isPresent()) {
            return allOf(standardConstraint, rollbackAction.get().getConstraints());
        } else {
            return standardConstraint;
        }
    }

【问题讨论】:

  • 代码的 rollbackAction 部分给了我编译错误,无法自动导入

标签: android testing android-espresso ui-testing


【解决方案1】:

以上都不适合我。这是一个自定义匹配器,它完全消除了该约束并允许您单击视图

 onView(withId(yourID)).check(matches(allOf( isEnabled(), isClickable()))).perform(
            new ViewAction() {
                @Override
                public Matcher<View> getConstraints() {
                    return ViewMatchers.isEnabled(); // no constraints, they are checked above
                }

                @Override
                public String getDescription() {
                    return "click plus button";
                }

                @Override
                public void perform(UiController uiController, View view) {
                    view.performClick();
                }
            }
    );

【讨论】:

  • 以上解决方案均无效,但这个有效!谢谢@gorbysbm!
  • 太棒了!事实证明,您甚至可以删除以下部分:“.check(matches(allOf(isEnabled(), isClickable())))”并直接进入 .perform( new ViewAction() { @Override
  • 无法编译isEnabled()方法
  • 导入静态 android.support.test.espresso.matcher.ViewMatchers.isEnabled; @LavekushAgrawal
  • 在显示区域之外有一个ImageButton 怎么样。我怎么能点击它?它在RelativeLayout 里面,而不是ScrollView
【解决方案2】:

我认为没有任何简单、优雅的解决方案。 90% 约束是硬编码在GeneralClickAction 中的,并且类是最终的,所以我们不能覆盖getConstraints

我会根据 GeneralClickAction's code 编写您自己的 ViewAction,跳过 isDisplayingAtLeast 检查。

【讨论】:

  • 没有Guava库的可以在编译器报错时使用import android.support.test.espresso.core.deps.guava.base.Optional;
  • 这对我有用,并与下面安娜的回答一起使用。谢谢!
【解决方案3】:

您必须先滚动到按钮:

onView(withId(R.id.button_id)).perform(scrollTo(), click());

【讨论】:

  • 按钮在屏幕上可见,但按钮的某些部分不可见(由于设计原因)。
  • 那么您的问题没有足够的信息来回答它。添加更多详细信息。
  • @denys 为什么我会在 espresso 文档中看到这个:Note that in order to scroll the list you shouldn't use {@link ViewActions#scrollTo()} as * {@link Espresso#onData(org.hamcrest.Matcher)} handles scrolling.
  • @Igor 上面是否有任何信息表明我们正在寻找解决方案以单击列表中的按钮(即适配器)?不,所以,我们必须使用onView(...)。如果它是适配器中的一个按钮,那么根据文档肯定应该使用onData(...)
  • @IgorGanapolsky 原因是ListView 懒惰地创建视图,所以如果你想滚动到一个还不可见的项目,与该项目关联的视图可能还不存在。 onData 让我们可以安全地与可能没有关联视图的项目进行交互。 (我知道这是旧的,但万一有人有同样的问题......)
【解决方案4】:

这有助于我在运行测试时解决按钮可见性问题

public static ViewAction handleConstraints(final ViewAction action, final Matcher<View> constraints)
{
    return new ViewAction()
    {
        @Override
        public Matcher<View> getConstraints()
        {
            return constraints;
        }

        @Override
        public String getDescription()
        {
            return action.getDescription();
        }

        @Override
        public void perform(UiController uiController, View view)
        {
            action.perform(uiController, view);
        }
    };
}

public void clickbutton()
{
    onView(withId(r.id.button)).perform(handleConstraints(click(), isDisplayingAtLeast(65)));
}

【讨论】:

    【解决方案5】:

    Espresso 的默认点击需要查看 &gt; 90% 的可见性。您如何看待创建自己的click ViewAction? 像这样……

    public final class MyViewActions {
       public static ViewAction click() {
          return new GeneralClickAction(SafeTap.SINGLE, GeneralLocation.CENTER, Press.FINGER);
        }
    }
    

    此点击将点击您视图的中心。

    然后你可以像这样执行点击: onView(withId(....)).perform(MyViewActions.click());

    我希望它可以工作。

    【讨论】:

    • 我也希望如此,不幸的是这并没有超过约束,它会抛出同样的错误。还有其他建议吗?
    • 我现在已经把它包含在问题中了
    • 感谢您添加详细信息。您是在测试开始时还是在打开某些东西后单击它?为什么我要问......这也可能意味着图像没有加载......可以通过在点击之前添加Thread.sleep(1000);来测试......
    • 我打开一个视图,然后点击按钮。我试着睡了几秒钟,但没有帮助。能通过 90% 的规则就好了..
    • 在较新版本的 Espresso 中,不存在 SafeTap。可以使用 Tap.SINGLE。
    【解决方案6】:

    创建您自己的没有视图可见性限制的 ViewAction 类:

     public static ViewAction myClick() {
    
        return new ViewAction() {
            @Override
            public Matcher<View> getConstraints() {
                return ViewMatchers.isEnabled(); // no constraints, they are checked above
            }
    
            @Override
            public String getDescription() {
                return null;
            }
    
            @Override
            public void perform(UiController uiController, View view) {
                view.performClick();
            }
        };
    
    }
    

    然后使用它:

    onView(withId(R.id.your_view_id)).perform(myClick());
    

    Kotlin 版本:

    fun myClick(): ViewAction = object : ViewAction {
      override fun getConstraints(): Matcher<View> = ViewMatchers.isEnabled() // no constraints, they are checked above
    
      override fun getDescription(): String = ""
    
      override fun perform(uiController: UiController, view: View) {
        view.performClick()
      }
    }
    

    【讨论】:

      【解决方案7】:

      对于我最终在下面做的文本视图上的相同错误,上面发布的答案和其他 SO 问题有很大帮助。我确实尝试了scrollTo 方法,但由于某种原因,错误仍然存​​在。希望这对某人有所帮助。

              onView(allOf(withId(R.id.recycler_view), isDisplayed())).perform(RecyclerViewActions
                      .actionOnItem(hasDescendant(withText("my text")), click()));
      

      【讨论】:

        猜你喜欢
        • 2019-11-17
        • 1970-01-01
        • 2015-09-06
        • 1970-01-01
        • 1970-01-01
        • 2019-06-21
        • 2014-09-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多