2015-10-22 2 views
14

Когда у меня есть ProgressBar в макетах, которые отображаются при запуске некоторых эспрессо-тестов - то я бегу в:и индикаторы выполнения Эспрессо

Caused by: android.support.test.espresso.AppNotIdleException: Looped for 1670 iterations over 60 SECONDS. The following Idle Conditions failed . 

Что такое хороший способ обойти это? Нашли некоторые хакерские вещи, но искали хороший способ

ответ

7

У меня такая же проблема. Я не мог понять абсолютно изящное решение, но я тоже опубликую свой подход.

Что я пытался сделать, это переопределить indeterminateDrawable на ProgressBar. При наличии простой переносимой анимации не происходит, и тест Espresso не сталкивается с проблемой Idle.

К сожалению, main и androidTest обрабатываются одинаково. Я не нашел способ переопределить стили моего ProgressBar.

Теперь это привело к объединению некоторых идей от https://gist.github.com/Mauin/62c24c8a53593c0a605e#file-progressbar-java и How to detect whether android app is running UI test with 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); 
    } 

} 

Debug код:

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, в то время как класс я ищу это основание моих тестов эспрессо.

Плохо то, что вам нужно обновить весь свой код, чтобы использовать свой пользовательский ProgressBar. Но хорошо, что ваш код выпуска не оказывает существенного влияния на это решение.

2

Основанный на Thomas R. solution, другой подход заключается в том, чтобы изменить извлечение 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()); 
7

Если 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(); 
     } 
    }); 
} 
+1

Это работает для меня, и это кажется наиболее прямо вперед решение здесь. – MungoRae

+2

Это решение является лучшим, поскольку позволяет избежать изменения кода производства из-за тестирования – pablisco

4

У меня подобный вопрос. Тест завершился неудачно уже в первом вызове 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's 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(); 
+0

Спасибо! Очень полезно, когда появляется индикатор выполнения при создании активности. – thenaoh

+0

Это фантастическое решение. Я просто взял этот код и завернул его в статический '@ ClassRule'. Никаких изменений в коде приложения, который был именно тем, что я искал. –

0

Этот ответ может быть запоздалым. С эспрессо вы должны отключить анимацию.

В устройстве, в разделе Настройки> Параметры разработчика, отключите следующие 3 настройки:

окна шкалы анимации, масштаб анимации перехода, аниматор шкала длительности

https://developer.android.com/training/testing/espresso/setup.html#set-up-environment

Там является ответом на Testing progress bar on Android with Espresso by riwnodennyk

Но будьте осторожны UIAnimator

Внимание: Мы рекомендуем протестировать приложение с помощью пользовательского интерфейса Automator только тогда, когда вашего приложения должно взаимодействовать с системой, чтобы выполнить критический случай использования. Поскольку UI Automator взаимодействует с системными приложениями и пользовательскими интерфейсами, вам необходимо перезапустить и исправить тесты UI Automator после каждого обновления системы. Такие обновления включают обновления версии платформы Android и новые версии услуг Google Play. В качестве альтернативы использованию UI Automator, рекомендуем добавлять герметичные тесты или отделять ваш большой тест на набор небольших и средних тестов . В частности, сосредоточьтесь на тестировании одной связи между приложениями за один раз, например, отправьте информацию в другие приложения и ответьте на результаты намерений. Инструмент Espresso-Intents может помочь вам написать эти более мелкие тесты.

https://developer.android.com/training/testing/fundamentals.html#large-tests

Смежные вопросы