2015-10-22 15 views
14

Kiedy mam ProgressBar w układach, które są wyświetlane podczas uruchamiania niektórych Ekspres do testów - potem napotkasz:ProgressBars i Espresso

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

Co to jest dobry sposób, aby obejść ten problem? Znalazłem jakieś hackowe rzeczy, ale szukając fajnego sposobu.

Odpowiedz

7

Mam ten sam problem. Nie mogłem wymyślić całkowicie eleganckiego rozwiązania, ale podam też moje podejście.

Co starałem się zastąpić indeterminateDrawable na ProgressBar. W przypadku prostego losowania animacja nie jest przeprowadzana, a test Espresso nie pojawia się w stanie Bezczynności.

Niestety main i androidTest są traktowane tak samo. Nie znalazłem sposobu na zastąpienie stylów mojego ProgressBar.

Teraz zakończyło się łączeniem niektórych pomysłów z https://gist.github.com/Mauin/62c24c8a53593c0a605e#file-progressbar-java i How to detect whether android app is running UI test with Espresso.

Najpierw stworzyłem niestandardowe klasy ProgressBar, jeden do debugowania i jeden do wydania. Wersja Release tylko wywołuje super konstruktorów i nie robi nic więcej. Wersja debugowania zastępuje metodę setIndeterminateDrawable. Dzięki temu mógłbym ustawić proste ciągnięcie zamiast animowanego. Kod

Release: Kod

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; 
    } 

} 

Jak widać Dodałem też sprawdzić, czy moja aplikacja jest uruchomiona test espresso, podczas gdy klasa szukam jest podstawa moich testów Espresso.

To, że musisz zaktualizować cały kod, aby użyć niestandardowego paska postępu. Ale dobrą rzeczą jest to, że twój kod zwolnienia nie ma większego wpływu na to rozwiązanie.

2

Na podstawie Thomas R. solution, innym podejściem jest zmiana losowania ProgressBar w teście, aby uniknąć modyfikacji kodu produkcyjnego.

Przykład:

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

Jeśli ProgressBar jest niewidoczny podczas uruchamiania testu, Drawable może być zastąpiony przez zwyczaju 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()); 

Zwyczaj 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

ten pracował dla mnie i wydaje się, że najbardziej prostego rozwiązania do przodu tutaj. – MungoRae

+2

To rozwiązanie jest najlepsze, ponieważ unika konieczności modyfikacji kodu produkcyjnego z powodu testowania. – pablisco

4

Mam podobne kwestia. Test zakończył się niepowodzeniem już w pierwszym wywołaniu funkcji getActivity(). Tak więc nieokreślone losowanie ProgressBar musi zostać zastąpione po rozpoczęciu aktywności.

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

Dzięki! Bardzo przydatne, gdy pasek postępu pojawia się podczas tworzenia działania. – thenaoh

+0

To fantastyczne rozwiązanie. Po prostu wziąłem ten kod i zapakowałem go w statyczny '@ ClassRule'. Żadnych zmian w kodzie aplikacji, które były dokładnie tym, czego szukałem. –

0

Ta odpowiedź może być za późna. Przy espresso musisz wyłączyć animację.

W urządzeniu, w obszarze Ustawienia> Opcje programisty, wyłącz 3 następujących ustawień:

Okno skalę animacja, Transition skala animacji, Animator skala trwania

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

Nie to odpowiedź pod numerem Testing progress bar on Android with Espresso autorstwa riwnodennyk

Ale bądź ostrożny UIAnimator

uwaga: zalecamy przetestowanie aplikacji przy użyciu interfejsu Automator tylko gdy aplikacja musi współdziałać z systemem spełnić krytyczny przypadek użycia. Ponieważ interfejs użytkownika automatów współpracuje z aplikacjami systemowymi i interfejsami użytkownika, po każdej aktualizacji systemu należy ponownie przeprowadzić testy UI Automatora i naprawić je. Aktualizacje takie: obejmują aktualizacje wersji platformy Android i nowe wersje usług Google Play w wersji . Jako alternatywę dla UI Automator, zalecamy zalecenie dodania testów hermetycznych lub rozdzielenie dużego testu na zestaw małych i średnich testów . W szczególności skup się na testowaniu jednego egzemplarza komunikacji między aplikacjami w czasie, na przykład wysyłaniu informacji do innych aplikacji i reagowaniu na zamierzone wyniki. Narzędzie do intencji espresso może pomóc Ci w napisaniu tych mniejszych testów.

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

Powiązane problemy