0

I have a class which is under a test with Robotium, in it's onPause() method I just clear the EditText (I don't need the data to be preserved after onPause()).

So I have in a class which is under a test:

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

and testing method:

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

        getInstrumentation().callActivityOnPause(mActivity);
    }

But then I got an error:

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)

If I use solo.setActivityOrientation(Solo.LANDSCAPE) I don't get this error.

Then if I wrap the mEdtPassword.setText("") with runOnUiThread() everything is fine.

So the questions are:

  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.

  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?

Thank you very much for clarification.

Eugene
  • 59,186
  • 91
  • 226
  • 333

2 Answers2

0

So that's what I know about this which might help you:

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.

As per the javadoc of callActivityOnPause()

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

So it would call the onPause() on its on thread which is not the UI thread. Now since you are setting value to and edit text in the Activity onPause() it would through error. So the cause of the error in setting value on your EditText. Since you are not doing any UI operation in the setActivityOrientation() it does not throw any error.

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?

I would answer point two and three together. You don't need to change you activity to make it testable. If you now that the activity method that you are testing are performing UI related task then you can put the UiThreadTest annotation to you test method. You can also read this link for more info..

My knowledge is only come from reading the java doc I have not tested it on my own. So please give it a go and let me know how it worked..

Russia Must Remove Putin
  • 374,368
  • 89
  • 403
  • 331
Praful Bhatnagar
  • 7,425
  • 2
  • 36
  • 44
0

Praful is mostly correct although I believe you are unable to use instrumentations methods within a test annotated with @UiThreadTest. This means your best option is in fact to wrap instrumentations method in a runnable that you can post to the main thread. for instance:

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

I havent tried this code, so its probably wrong, just killing time on the train!

Paul Harris
  • 5,769
  • 1
  • 25
  • 41