Проверка панели выполнения на Android с эспрессо - программирование
Подтвердить что ты не робот

Проверка панели выполнения на 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()));
        }
    });
4b9b3361

Ответ 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()))
}

и проверка будет ждать изменения видимости прогресса