首页 > 解决方案 > 带有自定义 KeyboardView 按钮的 Espresso 按下

问题描述

我在我的应用程序中实现了一个自定义 KeyboardView,目前一切正常,但是,当我尝试使用 Espresso ViewAction 按下键盘上的一个键时,我收到一个异常消息:

android.support.test.espresso.PerformException: 
Error performing 'single click - At Coordinates: 1070, 2809 and 
precision: 16, 16' on view 'with id: 
com.example.app.mvpdemo:id/keyboardLayout'.

抛出异常的代码是:

@Test
fun enter100AsPriceShouldDisplay120ForA20PercentTip(){
    onView(withId(R.id.editTextCheckAmount))
            .perform(typeText("100"), closeSoftKeyboard())
    val appContext = InstrumentationRegistry.getTargetContext()
    val displayMetrics = appContext.resources.displayMetrics
    onView(withId(R.id.keyboardLayout)).perform(clickXY(displayMetrics.widthPixels - 10, displayMetrics.heightPixels - 10))
    onView(withText("$120.00")).check(matches(isDisplayed()))
}

以及来自这篇文章的点击 XY 功能

 private fun clickXY(x: Int, y: Int): ViewAction {
    return GeneralClickAction(
            Tap.SINGLE,
            CoordinatesProvider { view ->
                val screenPos = IntArray(2)
                view.getLocationOnScreen(screenPos)

                val screenX = (screenPos[0] + x).toFloat()
                val screenY = (screenPos[1] + y).toFloat()

                floatArrayOf(screenX, screenY)
            },
            Press.FINGER, 0, 0)
}

这是我的键盘布局(固定在 ConstraintLayout 内的屏幕底部):

在此处输入图像描述

有谁知道为什么?任何帮助表示赞赏。

标签: androidandroid-espressocustom-keyboard

解决方案


在确定灵活的解决方案后回答我自己的问题:

  1. 第一次尝试 - 获取DisplayMetricsView并减去任意数字以尝试命中Keyboard.Key
    • 这不起作用,因为 clickXY 函数使用视图的位置
    • 这最终成为异常的原因,因为视图小于 DisplayMetrics 值,并且添加到屏幕位置上的视图将为 x 和 y 提供非常高的数字。

于是我又试了一次,

  1. 第二次 尝试使用check方法ViewMatcher检查KeyBoardView
    • 通过这样做,我能够访问KeyboardView的位置 x
    • 然后我能够得到KeyboardView的宽度和高度
    • 通过执行一些数学运算,我能够找出 x & y 的目标索引

数学:

  • 取宽度百分比Keyboard.Key(在我的情况下为 33.3%)
  • 取keyboard.xml的rowCount(在我的例子中是3)
  • 使用 (viewWidth * widthPercent) / 4 获取 relativeButtonX
  • 使用 (viewHeight / rowCount) / 2 获取 relativeButtonY
  • 然后对于targetY,我取了viewHeight - relativeButtonY
  • 最后,对于 targetX,我选择了 (viewPosX + viewWidth) - relativeButtonX

足够的解释,这里是代码:

@Test
fun enter100AsPriceShouldDisplay120ForA20PercentTip() {
    onView(withId(R.id.editTextCheckAmount))
            .perform(typeText("100"), closeSoftKeyboard())

    // call the function to get the targets
    val (viewTargetY, viewTargetX) = getTargetXAndY()

    // perform the action
    onView(withId(R.id.keyboardLayout)).perform(clickXY(viewTargetX.toInt(), viewTargetY))
    onView(withText("Tip: $20.00")).check(matches(isDisplayed()))
    onView(withText("Total: $120.00")).check(matches(isDisplayed()))
}

以及所有数学的辅助方法:

private fun getTargetXAndY(): Pair<Int, Double> {
    var viewHeight = 0
    var viewWidth = 0
    var viewPosX = 0F
    val viewMatcher = onView(withId(R.id.keyboardLayout))
    viewMatcher.check { view, _ ->
        viewWidth = view.width
        viewHeight = view.height
        viewPosX = view.x
    }

    val keyboardKeyWidthPercent = 0.333
    val keyboardRowsCount = 3

    val keyboardButtonWidthQuarter = (viewWidth * keyboardKeyWidthPercent) / 4
    val keyboardButtonHeightHalf = (viewHeight / keyboardRowsCount) / 2

    val viewTargetY = viewHeight - keyboardButtonHeightHalf
    val viewTargetX = (viewPosX + viewWidth) - keyboardButtonWidthQuarter
    return Pair(viewTargetY, viewTargetX)
}

现在,单击不是完全居中,但它单击的按钮非常接近中心。

我希望这对其他人有帮助!祝你好运,编码快乐!


推荐阅读