ProgressBars и Espresso
Когда у меня есть ProgressBar в макетах, которые отображаются при запуске некоторых эспрессо-тестов, тогда я сталкиваюсь с:
Caused by: android.support.test.espresso.AppNotIdleException: Looped for 1670 iterations over 60 SECONDS. The following Idle Conditions failed .
Какой хороший способ обойти это? Нашли некоторые хакерские вещи, но искали хороший способ
Ответы
Ответ 1
У меня та же проблема. Я не мог понять абсолютно изящное решение, но я также опубликую свой подход.
Что я пытался сделать, это переопределить indeterminateDrawable
на ProgressBar. При наличии простой анимации без анимации и теста Espresso не возникает проблема с простоя.
К сожалению, main
и androidTest
обрабатываются одинаково. Я не нашел способ переопределить стили моего ProgressBar.
Теперь это привело к объединению некоторых идей из https://gist.github.com/Mauin/62c24c8a53593c0a605e#file-progressbar-java и Как определить, Android-приложение запускает UI-тест с помощью Espresso.
Сначала я создал пользовательские классы ProgressBar, один для отладки и один для выпуска. Версия выпуска только вызывает суперконструкторы и ничего не делает. Отладочная версия переопределяет метод setIndeterminateDrawable
. С этим я мог бы установить простой вариант, а не анимационный.
Код выпуска:
public class ProgressBar extends android.widget.ProgressBar {
public ProgressBar(Context context) {
super(context);
}
public ProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
}
Отладочный код:
public class ProgressBar extends android.widget.ProgressBar {
public ProgressBar(Context context) {
super(context);
}
public ProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@SuppressWarnings("deprecation")
@Override
public void setIndeterminateDrawable(Drawable d) {
if (isRunningTest()) {
d = getResources().getDrawable(R.drawable.ic_replay);
}
super.setIndeterminateDrawable(d);
}
private boolean isRunningTest() {
try {
Class.forName("base.EspressoTestBase");
return true;
} catch (ClassNotFoundException e) {
/* no-op */
}
return false;
}
}
Как вы можете видеть, я также добавил чек, если мое приложение запускает тест Espresso, тогда как класс, который я ищу, является базой моих тестов Espresso.
Плохо то, что вам нужно обновить весь свой код, чтобы использовать свой собственный ProgressBar. Но хорошо, что ваш код выпуска не оказывает существенного влияния на это решение.
Ответ 2
Если ProgressBar
невидимо при запуске теста, Drawable
можно заменить обычным ViewAction
:
// Replace the drawable with a static color
onView(isAssignableFrom(ProgressBar.class)).perform(replaceProgressBarDrawable());
// Click a button (that will make the ProgressBar visible)
onView(withText("Show ProgressBar").perform(click());
Пользовательский ViewAction
:
public static ViewAction replaceProgressBarDrawable() {
return actionWithAssertions(new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isAssignableFrom(ProgressBar.class);
}
@Override
public String getDescription() {
return "replace the ProgressBar drawable";
}
@Override
public void perform(final UiController uiController, final View view) {
// Replace the indeterminate drawable with a static red ColorDrawable
ProgressBar progressBar = (ProgressBar) view;
progressBar.setIndeterminateDrawable(new ColorDrawable(0xffff0000));
uiController.loopMainThreadUntilIdle();
}
});
}
Ответ 3
У меня подобная проблема. Тест завершился неудачно уже в первом вызове getActivity(). Таким образом, неопределенный перенос ProgressBar должен быть заменен после начала действия.
Application application = (Application)this.getInstrumentation().getTargetContext().getApplicationContext();
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
//not here, it too early
}
@Override
public void onActivityStarted(Activity activity) {
//find the progressBar in your activity
ProgressBar progressBar = ((ProgressBar) activity.findViewById(R.id.progress_bar));
if(progressBar != null) {
//replace progress bar drawable as not animated
progressBar.setIndeterminateDrawable(new ColorDrawable(0xffff0000));
}
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
//Now you can start the activity
getActivity();
Ответ 4
Основываясь на решении Thomas R., другой подход заключается в том, чтобы изменить извлечение ProgressBar в тесте, чтобы избежать изменения производственного кода.
Пример:
Activity activity = startActivity();
// override progress bar infinite animation with a simple image
ProgressBar progressBar = (ProgressBar) activity.findViewById(R.id.loading_progressbar);
progressBar.setIndeterminateDrawable(activity.getDrawable(android.R.drawable.ic_lock_lock));
// click on the button that triggers the display of the progress bar
onView(withId(R.id.login_button)).perform(click());
Ответ 5
Этот ответ может быть запоздалым. С эспрессо вы должны отключить анимацию.
На вашем устройстве в разделе "Настройки" > "Параметры разработчика" отключите следующие 3 настройки:
Шкала анимации окон, масштаб анимации перехода, масштаб анимации аниматора
https://developer.android.com/training/testing/espresso/setup.html#set-up-environment
Есть ответ на тестовый индикатор выполнения на Android с эспрессо от riwnodennyk
Но будьте осторожны с UIAnimator
Внимание: мы рекомендуем тестировать ваше приложение с помощью UI Automator только тогда, когда ваше приложение должно взаимодействовать с системой для выполнения критического варианта использования. Поскольку UI Automator взаимодействует с системными приложениями и пользовательскими интерфейсами, вам необходимо повторите запуск и исправьте свои тесты Automation UI после каждого обновления системы. такие обновления включают обновления версии платформы Android и новые версии Службы Google Play. В качестве альтернативы использованию UI Automator мы рекомендуем добавлять герметичные тесты или отделять ваш большой тест на набор небольших и средних тестов. В частности, сосредоточьтесь на тестировании одного единый обмен сообщениями между приложениями, например, отправка информацию в другие приложения и ответы на результаты намерений. Инструмент Espresso-Intents может помочь вам написать эти более мелкие тесты.
https://developer.android.com/training/testing/fundamentals.html#large-tests