Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When testing android UI what's the proper way of waiting for UI to be ready?

The test looks like that (it's ActivityInstrumentationTestCase2):

public void testItShowsThreeRows() {
  activity = getActivity();

  activity.runOnUiThread(new Runnable() {
    public void run() {
      AccountsList accountsList = new AccountsList(activity, accounts);
      list.show();
    }
  });

  ListView listView = (ListView)activity.findViewById(R.id.list);
  assertEquals(3, listView.getChildCount());
}

The code I'm trying to test works. But the test fails because activity.runOnUiThread returns immediately. I can insert Thread.sleep and the test turns green but it looks kinda clumsy to me. Do I have to use some thread synchronization or may be poll for some UI element to be ready?

I tried to annotate it with @UiThreadTest but that doesn't work either. The code in list.show() populates a ListView via custom adapter and getView is called on another thread (not the one test runs on - and I have nothing to do with that, I have no threads or asynctasks, no nothing). The test fails again because it returns before UI is ready to be checked.

like image 872
Art Shayderov Avatar asked Feb 22 '12 19:02

Art Shayderov


2 Answers

Calling waitForIdleSync() is better than sleeping for a fixed time.

like image 116
Mike Playle Avatar answered Oct 19 '22 11:10

Mike Playle


You have to do a Thread.sleep. I don't think there's a way around this. I don't see why that's "clunky"; you're doing a test, so you have to wait for the system to show the UI element you want to test.

It seems to me, though, that you're really trying to test AccountsList or list. There's little reason to test ListView or findViewById unless you're paranoid.

You should focus on testing AccountsList and your custom adapter. You shouldn't have to use the UI to do this.

like image 43
Joe Malin Avatar answered Oct 19 '22 11:10

Joe Malin