Проверка панели выполнения на Android с эспрессо
Рабочий процесс должен быть следующим:
- Начало активности
- Индикатор выполнения отображается
- Пожары сетевого запроса (ресурс холостого хода уже зарегистрирован, поэтому эспрессо знает, как его ждать).
- Панель выполнения скрыта
- Отображается текст из сети.
До этого момента я написал утверждения для шагов 1, 3, 5, и он отлично работает:
onView(withText("foo 1"))
.check(matches(isDisplayed()));
Проблема заключается в том, что я понятия не имею, как сообщить espresso для проверки видимости индикатора выполнения до запроса и после запроса. p >
Рассмотрим метод onCreate()
:
super.onCreate(...);
setContentView(...);
showProgressBar(true);
apiClient.getStuff(new Callback() {
public void onSuccess() {
showProgressBar(false);
}
});
Я пробовал следующее, но он не работает:
// Activity is launched at this point.
activityRule.launchActivity(new Intent());
// Up to this point, the request has been fired and response was
// returned, so the progress bar is now GONE.
onView(withId(R.id.progress_bar))
.check(matches(isDisplayed()));
onView(withId(R.id.progress_bar))
.check(matches(not(isDisplayed())));
Причина, по которой это происходит, заключается в том, что, поскольку клиент зарегистрирован как ресурс бездействия, espresso будет ждать, пока он будет idle снова, прежде чем запускать первый onView(...progressbar...)...
, поэтому мне нужно, чтобы espresso знает, чтобы запустить это, прежде чем идти в режим ожидания.
EDIT: тоже не работает:
idlingResource.registerIdleTransitionCallback(new IdlingResource.ResourceCallback() {
@Override
public void onTransitionToIdle() {
onView(withId(R.id.progress_bar))
.check(matches(isDisplayed()));
}
});
Ответы
Ответ 1
У эспрессо есть проблемы с анимацией. Вы можете просто установить для рисования индикатора выполнения что-то статическое только для теста, и оно работает так, как ожидалось.
Drawable notAnimatedDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.whatever);
((ProgressBar) getActivity().findViewById(R.id.progress_bar)).setIndeterminateDrawable(notAnimatedDrawable);
onView(withId(R.id.progress_bar)).check(matches(isDisplayed()));
Ответ 2
Похоже, что это может быть действительно невозможно. Хотя это старая публикация в группах, есть довольно решающий ответ в Android Test Kit Discussion, где указано, что потоки пользовательского интерфейса не используются, t во время анимации индикаторов выполнения, и поэтому среда Espresso не может выполнить.
Marcus Klepp рекомендует переместить это здесь с помощью типов сборки. Плагин Gradle позволит вам определить различные типы . Вы можете настроить другой макет в свой тип сборки androidTest
, который заменяет View
на что-то общее. Если все, что вы делаете, подтверждает, что виджет isDisplayed()
в одном наборе условий и not(isDisplayed())
под другим набором условий, вы могли бы, конечно, реализовать это через разные файлы макета. Не то, чтобы это не было немного лифта.
Наконец, здесь может быть другая запись, в которой содержится дополнительная информация: "java.lang.RuntimeException: не удалось запустить умышленный запуск" для пользовательского интерфейса с неопределенным ProgressBar
Ответ 3
Как я вижу, Espresso
тесно связан с пропуском динамических действий пользовательского интерфейса, поэтому вы не можете протестировать ProgressBar
с помощью Espresso
. Однако вы можете легко выполнить это с помощью другого инструмента Google Android: UiAutomator
следующим образом:
saveButton().click(); // perform action opening ProgressBar with UiAutomator, not Espresso
assertTrue(progressBar().exists());
Использование этих статических utils:
public static UiObject progressBar() {
return uiObjectWithText(R.string.my_progress);
}
public static UiObject saveButton() {
return uiObjectWithId(R.id.my_save_button);
}
public static UiObject uiObjectWithId(@IdRes int id) {
String resourceId = getTargetContext().getResources().getResourceName(id);
UiSelector selector = new UiSelector().resourceId(resourceId);
return UiDevice.getInstance(getInstrumentation()).findObject(selector);
}
public static UiObject uiObjectWithText(@StringRes int stringRes) {
UiSelector selector = new UiSelector().text(getTargetContext().getString(stringRes));
return UiDevice.getInstance(getInstrumentation()).findObject(selector);
}
Убедитесь, что ваш build.gradle
включает в себя:
androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
Ответ 4
если вам нужно сделать это, вы можете использовать IdlingResource. основная идея - написать класс ресурсов холостого хода, который будет простаивать, когда видимость представления изменится.
что-то вроде того:
class ViewIdlingResource(private val view: View) : IdlingResource, ViewTreeObserver.OnGlobalLayoutListener {
var mIdle = false
private var mResourceCallback: IdlingResource.ResourceCallback? = null
private var stateChecker by Delegates.observable(view.isVisible()) { _, oldValue, newValue ->
if (oldValue != newValue) {
mIdle = oldValue != newValue
}
if (mIdle) {
mResourceCallback?.onTransitionToIdle()
}
}
init {
view.viewTreeObserver.addOnGlobalLayoutListener(this)
}
override fun getName(): String = "ViewIdlingResource"
override fun isIdleNow(): Boolean = mIdle
override fun registerIdleTransitionCallback(callback: IdlingResource.ResourceCallback?) {
mResourceCallback = callback
}
override fun onGlobalLayout() {
stateChecker = view.isVisible()
}
}
и использование это:
@Test
fun newOrderLandingPageTest() {
newOrderActivity.launchActivity(Intent())
idlingRegistery.register(ViewIdlingResource(newOrderActivity.activity.findViewById(R.id.pgLists)))
onView(withText(getTargetContext().getString(R.string.categories))).check(matches(isDisplayed()))
}
и проверка будет ждать изменения видимости прогресса