Android Espresso-如何检查是否可以单击视图

时间:2020-05-29 14:02:18

标签: android testing android-espresso ui-testing

我有一个带有启动屏幕的应用程序,该应用程序会停留约2秒钟。

此后,它切换到另一个活动A。 在A的{​​{1}}中设置一个值,然后单击SeekBar进行确认。

当我只是简单地开始录制的Espresso测试时,它会尝试在启动屏幕上播放。因此,当它尝试设置Button值或单击SeekBar时,我得到了Button。因此,我解决此问题的第一个尝试就是简单地添加一个NoMatchingViewException。这行得通。

但是,我不想在每次进行Activity切换后都进行手动睡眠。

  1. 因为它似乎是不必要的代码
  2. 因为这将意味着不必要的等待时间来运行测试
  3. 时间可能是任意的,并且对于不同的设备可能会有所不同

因此,我尝试检查我是否处于正确的活动中/是否可以看到正确的视图。我使用了一些SO链接:Wait for ActivityWait for View

但是,即使那样也不能100%工作。

我有以下两个功能:

sleep(5000)
fun <T: AppCompatActivity> waitForActivity(activity: Class<T>, timeout: Int = 5000, waitTime: Int = 100) {
    val maxTries = timeout / waitTime
    var tries = 0

    for(i in 0..maxTries) {
        var currentActivity: Activity? = null
        getInstrumentation().runOnMainSync { run { currentActivity = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(
            Stage.RESUMED).elementAtOrNull(0) } }
        if(activity.isInstance(currentActivity)) {
            break
        } else {
            tries++
            sleep(waitTime.toLong())
        }
    }
}

这些都不是100%有效的。他们两个似乎都在超时限制内返回,并“找到”了活动/视图。然而,预期的观点,例如fun waitForView( @IntegerRes id: Int, waitMillis: Int = 5000, waitMillisPerTry: Long = 100 ): ViewInteraction { // Derive the max tries val viewMatcher = allOf( withId(id), isDisplayed() ) val maxTries = waitMillis / waitMillisPerTry.toInt() var tries = 0 for (i in 0..maxTries) try { tries++ val element = onView(viewMatcher) element.check { view, noViewFoundException -> if(view == null) { throw noViewFoundException ?: Exception("TEST") } if(view.hasWindowFocus()) { throw noViewFoundException ?: Exception("TEST2") } } return element } catch (e: Exception) { if (tries == maxTries) { throw e } sleep(waitMillisPerTry) } throw Exception("Error finding a view matching $viewMatcher") } 尚未准备好执行,例如Button。它不会导致element.perform(click()),但是也不会执行我所做的点击。对于NoMatchingViewException,我使用以下方法:

SeekBar

但是,当我使用这些功能并短暂睡眠时,例如private fun setSeekValue(seekBar: ViewInteraction, age: Int) { val fullPercentage = .9f val step = 1/99f seekBar.perform( GeneralClickAction( Tap.SINGLE, CoordinatesProvider { view -> val pos = IntArray(2) view?.getLocationOnScreen(pos) FloatArray(2).apply { this[0] = pos[0] + view!!.width * (.05f + fullPercentage*step*age) this[1] = pos[1] + view.height * .5f } }, PrecisionDescriber { FloatArray(2).apply { this[0] = .1f this[1] = 1f } }, InputDevice.SOURCE_MOUSE, MotionEvent.ACTION_BUTTON_PRESS ) ) } 之后就可以了。但是,这再次违背了上面列出的三个原因,在这里我试图避免这种情况。

如您在函数sleep(100)中所见,我尝试使用waitForView检查视图是否“可用”。但这仍然不执行点击,除非我再次放置hasWindowFocus()之后。因此,它等待启动画面切换到sleep(80),找到它要查找的视图,然后无法执行单击,除非我稍等一下。

我还尝试了A的以下功能:

  • isEnabled
  • 已显示
  • 可见度
  • getDrawingRect
  • isFocusable
  • 被关注
  • isLayoutDirectionResolved

他们都不如我预期的那样工作。对于所有这些元素,在View的{​​{1}}部分返回了所需的值之后,如果不加上简短的element.check,仍然无法访问它们。

有没有一种方法可以可靠地检查我是否可以执行视图点击/可以安全地执行waitForView

通过检查活动是否已完全加载到可以使用其视图的点。或者直接检查视图是否可用。

0 个答案:

没有答案
相关问题