2013-02-12 162 views
0

我有一個正在使用Robotium進行測試的類,它的onPause()方法我只是清除了EditText(我不需要在onPause()之後保存數據)。runOnUiThread使用技巧

所以我有一個類,這是一個測試下:

@Override 
protected void onPause() { 
    super.onPause(); 
    mEdtPassword.setText(""); 
} 

和測試方法:

public void testOnPauseOnStart() { 
     Activity mActivity = getActivity(); 
     solo.typeText(0, CORRECT_PASSWORD); 

     getInstrumentation().callActivityOnPause(mActivity); 
    } 

但後來我得到了一個錯誤:如果我

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4746) 
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:854) 
at android.view.ViewGroup.invalidateChild(ViewGroup.java:4077) 
at android.view.View.invalidate(View.java:10322) 
at android.widget.TextView.invalidateRegion(TextView.java:4395) 
at android.widget.TextView.invalidateCursor(TextView.java:4338) 
at android.widget.TextView.spanChange(TextView.java:7186) 
at android.widget.TextView$ChangeWatcher.onSpanAdded(TextView.java:8821) 
at android.text.SpannableStringBuilder.sendSpanAdded(SpannableStringBuilder.java:979) 
at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:688) 
at android.text.SpannableStringBuilder.setSpan(SpannableStringBuilder.java:588) 
at android.text.Selection.setSelection(Selection.java:76) 
at android.text.Selection.setSelection(Selection.java:87) 
at android.text.method.ArrowKeyMovementMethod.initialize(ArrowKeyMovementMethod.java:302) 
at android.widget.TextView.setText(TextView.java:3555) 
at android.widget.TextView.setText(TextView.java:3425) 
at android.widget.EditText.setText(EditText.java:80) 
at android.widget.TextView.setText(TextView.java:3400) 
at <package>.ui.CheckPasswordActivity.onPause(CheckPasswordActivity.java:182) 

使用solo.setActivityOrientation(Solo.LANDSCAPE)我沒有得到這個錯誤。

然後,如果我包裝mEdtPassword.setText("")runOnUiThread()一切都很好。

所以問題是:

  1. 爲什麼當我使用solo.setActivityOrientation()我沒有這個例外,但我做的,當我使用getInstrumentation().callActivityOnPause(mActivity),我相信雙方都在做同樣的事情。

  2. 要我換東西像mEdtPassword.setText("")onPause()runOnUiThread其他地方其他原因或者我只需要它用於測試目的?

  3. 是否意味着如果我想測試我的UI我需要編寫更多的代碼(如在UI線程上運行日常操作)才能運行它們?

非常感謝您的澄清。

+0

可以顯示完整的logcat跟蹤... – 2013-02-12 11:12:21

+0

@PrafulBhatnagar完成。現在我知道問題所在。如果你願意的話,還是希望聽到這三個問題的答案。 – Eugene 2013-02-12 11:17:14

回答

0

儘管我相信你無法在使用@UiThreadTest註釋的測試中使用instruments方法,但Praful基本上是正確的。這意味着你最好的選擇實際上是將儀器方法封裝在一個可運行的,你可以發佈到主線程。例如:

public void callActivityOnPause(final Activity activity){ 
    getInstrumentation().runOnMainSync(new Runnable() { 
      public void run() { 
       activity.onpause(); 
      } 
     }); 
} 

我還沒試過這個代碼,所以它可能錯了,只是在火車上消磨時間!

0

所以這就是我知道這可能幫助您:

1) Why I don't have this exception when I use solo.setActivityOrientation() but I do when I use getInstrumentation().callActivityOnPause(mActivity), I presume both are doing the same thing.

爲每callActivityOnPause()

Perform calling of an activity's onPause() method. The default implementation simply calls through to that method.

的Javadoc因此,這將呼籲其onPause()上線這是不UI線程。現在,因爲您正在設置值並編輯ActivityonPause()中的文本,它會通過錯誤。所以在你的EditText上設置值的錯誤的原因。由於您在setActivityOrientation()中沒有執行任何UI操作,因此不會引發任何錯誤。

2) Shall I wrap things like mEdtPassword.setText("") in onPause() with runOnUiThread somewhere else for some other reasons or I just need it for testing purposes?

3) Does it mean if I want to have tests of my UI I need to write more code (like running ordinar operations on UI thread) to make it possible to run them?

我會回答第二點和第三點在一起。你不需要改變你的活動來使其可測試。如果您現在正在測試的活動方法正在執行與UI相關的任務,那麼您可以將UiThreadTest註釋添加到您的測試方法中。你也可以閱讀這link欲瞭解更多信息..

我的知識只來自閱讀java文檔我沒有測試過我自己的。所以請給它一個去讓我知道它是如何工作的..