按钮上的Android Espresso错误点击

时间:2015-12-29 12:05:08

标签: android android-espresso ui-testing

我正在尝试使用espresso框架为Android APP编写一些UI测试。

现在我只是检查启动画面上是否存在所有元素,然后我尝试点击登录按钮。

单击该按钮时,测试失败,因为我无法理解为什么会发生错误。

我的测试代码是

@RunWith(AndroidJUnit4.class)
@SmallTest
public class WelcomeTest {

  @Rule
  public ActivityTestRule<Welcome> mActivityRule = new ActivityTestRule<>(
          Welcome.class);

  @Test
  public void elements_present() {
      // Check login
      onView(withId(R.id.wv_login)).check(matches(isDisplayed()));
      // Check signup
      onView(withId(R.id.wv_signup)).check(matches(isDisplayed()));
      // Check video
      onView(withId(R.id.videoView)).check(matches(isDisplayed()));
      // Check swipe right
      onView(withId(R.id.videoView)).perform(swipeRight());
      // Check swipe left
      onView(withId(R.id.videoView)).perform(swipeLeft());
  }

  @Test
  public void tap_login() {
      // Tap login button
      onView(withId(R.id.wv_login)).perform(click());
  }

}

我得到的输出是:

  

引起:java.lang.RuntimeException:由于目标视图与以下一个或多个约束不匹配,因此不会执行操作:   至少90%的视图区域会显示给用户。

这是什么意思,这是由我的测试方法引起的还是代码中的错误?该应用似乎在我的设备上运行良好。

PS:我已经禁用动画,因为espresso文档建议

3 个答案:

答案 0 :(得分:10)

  

引起:java.lang.RuntimeException:不会执行操作   因为目标视图与以下一个或多个不匹配   约束:显示至少90%的视图区域   用户。

当任何预期的视图未完全可见时,我会发生这种情况,默认情况下,Espresso正在寻找在设备屏幕上完全可见的元素。

似乎您的实际设备屏幕不显示您的登录活动xml文件的全部内容。

  • 您使用ScrollView还是ListView
  • 您的布局如何?
  • 它是否完全显示在经过测试的设备上?

这可能会有所帮助:

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

我的问题仍然会发生,请您添加问题xml或截图。我会解决它; - )

  

注意:检查某些东西是否完全可见(这意味着更多   90%)你可以使用

onView(withId(R.id.wv_login)).check(matches(isCompletelyDisplayed()));
     

而不是:

onView(withId(R.id.wv_login)).check(matches(isDisplayed()));

在更大的屏幕设备上运行测试,检查它是否仍然存在。

如果您有疑问,请随意提问

答案 1 :(得分:2)

此处RuntimeException显示的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.实际上来自View无法完全显示。然而,@ piotrek1543给出的答案并没有真正找到解决方案,尽管它充满了非常好的信息。

问题是由竞争条件引起的。您正在尝试打开视图,在打开视图期间,您尝试单击它。如果时机不对,那么View中只有不到90%的Es click()可用于Developer Options。您可以按The Espresso Setup Instructions

中的建议停用动画来解决此问题
  • 导航至您的手机Transition Animation Scale
  • 设置以下内容
    • 窗口动画比例= 0.0x
    • 过渡动画比例= 0.0x
    • 动画师持续时间刻度= 0.0x

我自己的测试表明,只需将0.0x设置为 $("#jqGridDel").jqGrid({ url: "Data.aspx/BindInfo", datatype: 'json', mtype: 'POST', serializeGridData: function (postData) { return JSON.stringify(postData); }, ajaxGridOptions: { contentType: 'application/json; charset=utf-8' }, ajaxSelectOptions: { type: 'POST', contentType: 'application/json; charset=utf-8', success: function (result) { alert("hello"); } },, colName: ['DelId', 'Name', 'DeliveryName', 'Status'], colModel: [ { label: 'Del No', name: 'DelId', width: 35 }, { label: 'Gate', name: 'Name', width: 200, editable: true, edittype: "select", foramtter: "Select", editoptions: { dataUrl: "Data.aspx/BindDDInfo", buildSelect: function (data) { alert(data); } } }, { label: 'Delivery', name: 'DeliveryName', width: 150, editable: true }, { label: 'Active', name: 'Status', width: 40, editable: true, align: "center", formatter: "checkbox", edittype: "checkbox", editoptions: { value: '1:0' } } ], loadonce: true, width: 1050, height: "100%", pager: "#jqGridDelPager", caption: "Configuration", rowNum: 15, jsonReader: { page: function (obj) { return 1; }, total: function (obj) { return 1; }, records: function (obj) { return obj.d.length; }, root: function (obj) { return obj.d; }, repeatitems: false, id: "QGDelId" }, onSelectRow: function (id) { if (id && id !== lastSelQGDel) { lastSelQGDel = id; } }, ajaxRowOptions: { contentType: 'application/json; charset=utf-8' }, serializeRowData: function (postData) { return JSON.stringify({ editQGData: postData }); }, editurl: "Data.aspx/SaveData" }); $('#jqGridDel').navGrid("#jqGridDelPager", { edit: false, add: false, del: false, refresh: false, search: false, view: false }); $('#jqGridDel').inlineNav('#jqGridDelPager', // the buttons to appear on the toolbar of the grid { edit: true, add: true, del: true, refresh: true, cancel: true, editParams: { keys: true, rowid: lastSelQGDel, restoreAfterError: true, reloadAfterSubmit: true, successfunc: function (result) { if (result.responseJSON.d == "Success") alert("Data saved successfully!!"); else alert("There is some error in data processing"); setTimeout(function () { $("#jqGridDel").jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid'); }, 50); } }, addParams: { keys: true, addRowParams: { successfunc: function (result) { if (result.responseJSON.d == "Success") alert("Data saved successfully!!"); else alert("There is some error in data processing"); setTimeout(function () { $("#jqGridDel").jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid'); }, 50); } } } 即可。您可以想象,这是您正在经历的竞争条件的完美一致的解决方案。

答案 2 :(得分:0)

如果未将按钮放置在滚动视图中并且关闭了动画,则当将按钮设置为高度并且在高度设置为wrap_content的父布局中时,会发生此错误。

失败

<LinearLayout
        ...
        android:layout_width="match_parent"
        **android:layout_height="wrap_content">**

        <com.google.android.material.button.MaterialButton
            android:id="@+id/btn_attendance"
            app:backgroundTint="@color/surveyColor"
            android:textAllCaps="false"
            android:text="View Attendance"
            android:layout_weight="1"
            android:layout_marginRight="5dp"
            android:layout_width="0dp"
            **android:layout_height="60dp"/>**
</LinearLayout>

Pass:高度值应该传递给父级布局

    <LinearLayout
        ...
        android:layout_width="match_parent"
        **android:layout_height="60dp">**

        <com.google.android.material.button.MaterialButton
            android:id="@+id/btn_attendance"
            app:backgroundTint="@color/surveyColor"
            android:textAllCaps="false"
            android:text="View Attendance"
            android:layout_weight="1"
            android:layout_marginRight="5dp"
            android:layout_width="0dp"
            **android:layout_height="60dp"/>**
</LinearLayout>