我有一个带有启动屏幕的应用程序,该应用程序会停留约2秒钟。
此后,它切换到另一个活动A
。
在A
的{{1}}中设置一个值,然后单击SeekBar
进行确认。
当我只是简单地开始录制的Espresso测试时,它会尝试在启动屏幕上播放。因此,当它尝试设置Button
值或单击SeekBar
时,我得到了Button
。因此,我解决此问题的第一个尝试就是简单地添加一个NoMatchingViewException
。这行得通。
但是,我不想在每次进行Activity切换后都进行手动睡眠。
因此,我尝试检查我是否处于正确的活动中/是否可以看到正确的视图。我使用了一些SO链接:Wait for Activity和Wait 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
的以下功能:
他们都不如我预期的那样工作。对于所有这些元素,在View
的{{1}}部分返回了所需的值之后,如果不加上简短的element.check
,仍然无法访问它们。
有没有一种方法可以可靠地检查我是否可以执行视图点击/可以安全地执行waitForView
通过检查活动是否已完全加载到可以使用其视图的点。或者直接检查视图是否可用。