2015-10-22 214 views
14

當我在佈局一個進度正在運行的一些咖啡,測試時顯示的 - 然後我跑到:ProgressBars和咖啡

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

什麼是一個很好的解決這樣?發現一些hackish的東西,但尋找一個不錯的方法

回答

7

我有同樣的問題。我無法弄清楚一個完美的解決方案,但我會發布我的方法。

我試圖做的是重寫ProgressBar上的indeterminateDrawable。當有一個簡單的drawable時,不會發生動畫,Espresso測試不會遇到空閒問題。

不幸的是mainandroidTest的處理方法是相同的。我沒有找到一種方法來覆蓋ProgressBar的樣式。

現在它結合了https://gist.github.com/Mauin/62c24c8a53593c0a605e#file-progressbar-javaHow to detect whether android app is running UI test with Espresso的一些想法。

起初,我創建了自定義的ProgressBar類,一個用於調試,另一個用於發佈。發佈版本只調用超級構造函數,不做別的。調試版本覆蓋方法setIndeterminateDrawable。有了這個,我可以設置一個簡單的drawable而不是動畫。

發行代碼:

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測試的基礎。

不好的一點是您必須更新所有代碼才能使用您的自定義ProgressBar。但好處是您的發行版代碼不會對此解決方案產生重大影響。

2

基於Thomas R. solution,另一種方法是更改​​測試中ProgressBar的drawable,以避免修改生產代碼。

實施例:

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的不確定drawable必須在活動開始後被替換。

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由riwnodennyk回答

但要謹慎UIAnimator

注意:我們建議您使用測試的Automator UI只有當 您的應用程序必須與系統交互來滿足關鍵用途情況下,你的應用程序。 由於UI Automator與系統應用程序和用戶界面交互,因此需要在每次系統更新後重新運行並修復UI Automator測試。這樣的 更新包括Android平臺版本升級和 Google Play服務的新版本。作爲使用UI Automator的替代方案,我們建議添加密封測試或將大型測試分爲 套小型和中型測試。尤其要重點測試一次應用程序間通信,例如將 信息發送到其他應用程序並對意圖結果進行響應。意大利濃咖啡工具可幫助您編寫這些較小的測試。

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