Android UI testing with robotium

Nico Heid's picture

android logo
I will base this post on the last article: Android ViewFlipper within TabHost for Tabs with different Views ... and better memory footprint, where we had a TabHost and a ViewFlipper. To test that our example is still working, we have to start the app, start the tab example, click on the ViewFlipper then change to Tab2 and press the button. Of course you can do this by hand if you must, which basically always happens when you're in the middle of development -unless you're doing test driven development. But later on, you don't really want to sit there and click a lot, or even worse, enter text with your thick fingers on a tiny android device screen. So a good idea to test the UI is to get it automated in some way. That is where robotium comes into the game.

Writing a basic test

So let's write a test that does what we mentioned above. Go through the view and press everything we got and make sure it behaves the way we want it to.

  1.     public void testTabExample() {
  2.         solo.clickOnText("start tab example");
  3.         solo.assertCurrentActivity("wrong activiy", Tabs.class);
  4.         solo.clickOnText("this is a tab one");
  5.         assertTrue(solo.searchText("this is the other tab one"));
  6.         solo.clickOnText("this is the other tab one");
  7.         assertTrue(solo.searchText("this is a tab one"));
  8.         solo.clickOnText("Tab2");
  9.         solo.clickOnText("do something");
  10.         assertTrue(solo.searchText("this is a tab two"));
  11.         sendKeys(KeyEvent.KEYCODE_BACK);
  12.         solo.assertCurrentActivity("wrong activiy", UCdroid.class);
  13.     }

What we doing here is clicking on the elements we see and clicking on the ones we need to click. We check that we're running the correct activity and that the right texts show up. The test will run fine now, but it's missing some abstraction. If we decide to rename a text later, we have to edit the test case. This is less than optimal. So let's see what we can change to improve the test case.

Changing the application for better testability

Let's take a look at the layout:

  1. <Button
  2.    android:id="@+id/btn_tabs"
  3.    android:text="start tab example"  
  4.    android:layout_width="fill_parent"
  5.    android:layout_height="wrap_content"
  6.    />

We can see, that the Button has a hard wired text. That gives us some trouble later, because we cannot look up the text in the string resources. A good idea is to place the appropriate string in strings.xml and put a reference to it in the layout. This has two benefits. First, we can now look up the string in our test case. Second, we now have all the strings we use in the application in one file. This is particularly helpful if we want to have internationalization in the application.

So here is our "new" button

  1. <Button
  2.    android:id="@+id/btn_tabs"
  3.    android:text="@+string/btn_start_tab_example"  
  4.    android:layout_width="fill_parent"
  5.    android:layout_height="wrap_content"
  6.    />

all we need in the strings.xml now is:
  1.  <string name="btn_start_tab_example">start tab example</string>

after we did this for all the strings we use we can continue.

Writing a more abstract test

So here is our improved test case. Now we do not need to fear changing strings or internationalization.

  1.     public void testTabExample() {
  2.         Activity a = getActivity();
  3.         String tab1c1 = a.getString(R.string.tab1_content1);
  4.         String tab1c2 = a.getString(R.string.tab1_content2);
  5.         String tab2c1 = a.getString(R.string.tab2_content1);
  6.        
  7.         solo.clickOnText(a.getString(R.string.btn_start_tab_example));
  8.         solo.assertCurrentActivity("wrong activiy", Tabs.class);<img src='http://pragmatic-geek.com/uc/sites/default/files/imagepicker/1/android_logo.jpg' alt='android logo' style="float: left" class="imgp_img" />
  9.         solo.clickOnText(tab1c1);
  10.         assertTrue(solo.searchText(tab1c2));
  11.         solo.clickOnText(tab1c2);
  12.         assertTrue(solo.searchText(tab1c1));
  13.         solo.clickOnText(a.getString(R.string.tabexample_tab2));
  14.         solo.clickOnText(a.getString(R.string.btn_do_something));
  15.         assertTrue(solo.searchText(tab2c1));
  16.         sendKeys(KeyEvent.KEYCODE_BACK);
  17.         solo.assertCurrentActivity("wrong activiy", UCdroid.class);
  18.     }

Robtium shortcomings

When looking at the robotium java doc I noticed two things so far which bothered me a bit. Maybe I had a wrong approach or didn't quite figure out how to do it.

When entering text via .enterText(int index, String text) I have to select the EditText field via its position in the layout instead of addressing it by its name. So as soon as the layout changes, I have to edit my test. Not so good.

The next thing is, when menus open and the item to click needs a scrolling action first I cannot reach it.

I'll try to tackle those issues and write another post on how to do more complex operations.

Robotium alternatives

calculon
To all the Futurama fans, there's another test framework which name has to sound familiar: Calculon. There is a short introduction on the author's blog. I might look into that too.

So stay tuned for updates on Android UI testing.

Check out the project and the test on github.

Comments

 Twitter Trackbacks for Android UI testing with robotium | u's picture

[...] Android UI testing with robotium | united-coders.com united-coders.com/nico-heid/android-ui-testing-with-robotium – view page – cached I will base this post on the last article: Android ViewFlipper within TabHost for Tabs with different Views ... and better memory footprint, where we had a TabHost and a ViewFlipper. To test that our example is still working, we have to start the app, start the tab example, click on the ViewFlipper then change to Tab2 and press the button. Of course you can do this by hand if you must, which... Read moreI will base this post on the last article: Android ViewFlipper within TabHost for Tabs with different Views ... and better memory footprint, where we had a TabHost and a ViewFlipper. To test that our example is still working, we have to start the app, start the tab example, click on the ViewFlipper then change to Tab2 and press the button. Of course you can do this by hand if you must, which basically always happens when you're in the middle of development -unless you're doing test driven development. But later on, you don't really want to sit there and click a lot, or even worse, enter text with your thick fingers on a tiny android device screen. So a good idea to test the UI is to get it automated in some way. That is where robotium comes into the game. View page Tweets about this link [...]

Ed's picture

Did you ever figure out how to grab the scrolling action ? My issue is an app that presents maps larger than
the viewable window, requiring that the screen slide left, right, up and down. It's not readily apparent what
event there is for this, that would be similar to solo.clickOnText(tab1c2);

Nico Heid's picture

are you using the moste recent robotium version?

i didn't test it myself, but i've seen in the changelog, that if you using a element capable of scrolling, and the text searched for is not visible, scrolling will be triggered now.

if it's not the case, i do not have a solution for it, but probably will look into it within the next few weeks.

dinesh's picture

Can you tell how did you find that value s as shown in example (R.string.tab2_content1). Here R is android class and string is its method and the value of variable where did you get ? Please explain.