Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing with UI elements in Android view

I am attempting to test simple UI with the following test case, The main idea is to set in the test some of the UI text (to mimic user input) and then actively click an event.

public class StackTestCase 
extends ActivityInstrumentationTestCase2<Stack> 
{
private StackDemo mActivity;

private EditText eaten;
    public StuckTestCase() {
         super("com.crocodil.software.stack", Stack.class);


    }
    public StuckTestCase(Class<Stack> activityClass) {
         super("com.crocodil.software.stack", activityClass);

    }
    protected void setUp() throws Exception {
        super.setUp();
        mActivity = this.getActivity();
        mCount = (Button) mActivity.findViewById(com.crocodil.software.stack.R.id.action);
        eaten = (EditText) mActivity.findViewById(com.crocodil.software.stack.R.id.eaten);

    }

    public void testPreconditions() {
        assertNotNull(mStatus);
      }

    public void testSimpleDefaults(){
        double status = Double.valueOf(mStatus.getText().toString());
        eaten.setText(2);
        mCount.performClick();
        assertEquals((status-2),Double.valueOf(mStatus.getText().toString()));
    }

}

the running result is the exception -

android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRoot.checkThread(ViewRoot.java:2802)
at android.view.ViewRoot.playSoundEffect(ViewRoot.java:2581)
at android.view.View.playSoundEffect(View.java:8516)
at android.view.View.performClick(View.java:2407)
at com.crocodil.software.stack.test.StackTestCase.testSimpleDefaults(StackTestCase.java:46)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:204)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:194)
at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:186)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:520)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)

This happens on each access to the UI elements and i was unable to avoid it by using handles or async task ? any suggestions?

like image 728
Croc Avatar asked Aug 29 '10 20:08

Croc


Video Answer


1 Answers

This is an old question, but I'm giving you an answer anyway, in case someone stumbles upon it.

You are not allowed to change states of UI widgets from anywhere but the main thread (UI thread). Your performClick must be done like this:

mActivity.runOnUiThread(new Runnable() {
  @Override
  public void run() {
    mCount.performClick();
  }
});

But that is not all, you will also need to sync your instrumentation test with the ui, by adding the following line:

getInstrumentation().waitForIdleSync();

The sync line is usually placed immediately after the runOnUiThread() code.

like image 101
Robert Avatar answered Oct 17 '22 22:10

Robert