У меня есть приложение с заставкой, которая остается около 2 секунд.
После этого оно переключается на другое действие A
. В A
я устанавливаю значение в SeekBar
, а после этого щелкаю Button
для подтверждения.
Когда я просто запускаю записанный тест эспрессо, делая это, он пытается воспроизвести, пока заставка. Поэтому, когда он пытался установить значение SeekBar
или щелкнуть Button
, я получил NoMatchingViewException
. Итак, моей первой попыткой исправить это было просто добавить sleep(5000)
. Это сработало.
Однако я не хочу переводить в спящий режим вручную после каждого переключения активности.
- Потому что это кажется ненужным кодом
- Потому что это будет означать ненужное время ожидания для запуска теста
- Время может быть произвольным и может отличаться для разных устройств
Поэтому я попытался проверить, прав ли я Активность / может видеть правильные просмотры. Я сделал это с помощью некоторых ссылок SO: Ожидание активности и Ожидание просмотра .
Однако даже это не работает на 100%.
У меня есть две функции:
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())
}
}
}
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")
}
Ни одна из них не работает на 100%. Оба они, кажется, возвращаются в рамках ограничений тайм-аута и «нашли» действие / представление. Однако ожидаемый вид, например 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)
после него, он работает. Это опять же go противоречит трем причинам, перечисленным выше, которых я здесь пытаюсь избежать.
Как вы можете видеть в функции waitForView
, я попытался проверить, является ли View " пригодный для использования », используя hasWindowFocus()
. Но при этом щелчок по-прежнему не выполняется, за исключением тех случаев, когда я снова ставлю sleep(80)
или что-то после него. Поэтому он ждет, пока экран-заставка переключится на A
, находит вид, который ищет, а затем не может выполнить щелчок, за исключением тех случаев, когда я немного подожду.
Я также пробовал эти функции View
:
- isEnabled
- isShown
- видимость
- getDrawingRect
- isFocusable
- isFocused
- isLayoutDirectionResolved
Ни один из них не работал так, как я ожидал. Со всеми из них после того, как необходимое значение было возвращено в element.check
части waitForView
, они все равно были бы недоступны, если бы после него не было короткого sleep
.
Есть ли способ чтобы надежно проверить, могу ли я выполнить щелчок по представлению / безопасно выполнить ViewInteraction.perform()
Либо путем проверки, полностью ли загружено действие до точки, в которой его представления можно использовать. Или напрямую проверив, можно ли использовать представление.