share
Stack OverflowBest practices for unit testing Android apps
[+795] [16] nyenyec
[2009-02-06 21:43:19]
[ android unit-testing tdd android-testing ]
[ http://stackoverflow.com/questions/522312/best-practices-for-unit-testing-android-apps ] [DELETED]

I'd like to unit test my Android application but I found that test driven development in Android is far from trivial at the moment.

Any tips, tricks, war stories for building light weight and preferably fast running tests?

(3) I came across this blog which seemed to have useful tips: dtmilano.blogspot.com/2008/03/… - Morendil
(47) i dont know why the moderator closed the question???? - Abhijit Chakra
(94) Very useful question, despite being general. Shame it was closed. - Jasper Blues
(3) Look at the answers that the question attracted. They're all over the map, and most of them say "try my favorite testing framework." - Robert Harvey
(26) @RobertHarvey: If not SO, then where does a question like this belong? A person who's looking for ways to unit test Android is probably looking for answers exactly like that. I certainly was when I came across this question. - Ryan Stewart
(22) Not constructive? 551 people seem to disagree... and this has been viewed >100k times. Seriously, I come across good SO questions that are closed pretty much on a daily basis. - twiz
(31) I vote to reopen because the answers are now out of date. We now have UiAutomator and also espresso as other good options that were not around a couple of years ago. At least allow one of the Mods to add those details somewhere useful please? - Richard Le Mesurier
(2) I also vote to reopen. The question is quite old, but it is still pops as one of the top search results in Google. The question and the answers are very constructive. Please reopen. - Yuriy Kulikov
(2) I vote to reopen too. As Ryan said, "If not SO, where does a question like this belong?" I cannot think of a better format for addressing this kind of question. SO's flexibility really helps one find the most helpful answers. - Alyoshak
This question appears on the first page of results searching for "testing in Android" so I think it should be updated with Espresso and the unit testing support in build tools 1.1+. - Jose Alcérreca
[+223] [2010-02-15 19:40:47] Renas

You should try Robotium! Go to Robotium.org [1] and download the example test project. Robotium is a really easy to use framework that makes testing of android applications easy and fast. I created it to make testing of advanced android applications possible with minimum effort. Its used in conjunction with ActivityInstrumentationTestCase2.

[1] http://code.google.com/p/robotium/

(2) that looks great, thanks for tip. - Matthias
(1) How did you get a referance to textviews, buttons and edittext's? I tried to reach them by enterText(R.id.myTextView, "Hello") but that did not work. enterText requires an int, which I assumes was the int index/name of the Textview in R.java. - Sara
(1) This seems to be easy for testing through performing clicks at a given time. But why not go with developer.android.com/guide/topics/testing/testing_android.html for deeper things? - OneWorld
(44) It is a blackbox testing framework - Vanuan
(19) Yeah - what Vanuan said...this is not a unit test framework. - Nick
youtube.com/watch?v=T_8euppCz3k A link to the youtube video by the authors, if you are looking to get started immediately :) - PCoder
(1) i think nowadays Expresso is much better and easier to use - Kitesurfer
1
[+198] [2010-11-18 02:57:12] Xian

Also worth checking out is Robolectric [1], an alternative approach to testing Android apps.

Instead of deploying your app and tests to the Android emulator (which can be very slow), Robolectric runs your tests directly in your computer's JVM, reducing typical test turnaround times from minutes to seconds.

Robolectric allows you to test most Android functionality including layouts and GUI behavior, services, and networking code. It offers much greater flexibility than Google's testing framework in testing some Android features, such as widgets and services.

[1] http://robolectric.org/

This seems to be a very useful library, thanks. - tichy
(5) I'm having problems with this. It could successfully shadow an activity, but I'm getting a null pointer exception when the tested source gets a resource. It's definitely fast. However, it's oriented toward the IntelliJ IDE, not Eclipse. There's limited support for it, and unless you want to delve into the source code and learn the model and debug the source on your own, I wouldn't recommend it. - Jack BeNimble
works great for me in eclipse. make sure you are using maven, maven-android, and maven-android-for-eclipse. - davidjnelson
@Jack BeNimble I am facing the same problem, i cannot get resource Xml files .. it is giving null pointer exception - Shahab
@devadvocate - Any ideas why using maven makes a difference? Are you successfully doing a getResource? - Jack BeNimble
Just mock your resources and continue unit testing: Mockito.stub(mockContext.getResources()).toReturn(mockResources); - Blundell
To get to the resource XML files in Robolectric, set the test config's working directory in the test config 'args' tab to the application directory, not the test one. - android.weasel
Robolectric is not update. - Saeed Zarinfam
2
[+56] [2010-10-04 13:53:02] paulovic

I've been working with Android Unit and Functional tests using the Instrumentation Framework. Its documentation is now clearer than in the past. These links can guide you to start testing:


(2) Link to "a code sample of these classes" and "a sample of how to test activities" seems to return 404 not found - Yko
3
[+38] [2009-02-15 13:51:18] Gian Marco Gherardi

Looking at ApiDemos sample app, i found ActivityUnitTestCase and ActivityInstrumentationTestCase classes.

Seems that these are utility classes for testing android programs.

Here are the links to the reference:
http://developer.android.com/reference/android/test/ActivityInstrumentationTestCase.html
and
http://developer.android.com/reference/android/test/ActivityUnitTestCase.html

Also android.jar includes a subset of JUnit test framework for plain old unit test. Take a look at ApiDemos sample for learning how to write and run it.

Hope this help!


(13) ActivityIntrumentationTestCase is now deprecated. The docs points to ActivityInstrumentationTestCase2: developer.android.com/reference/android/test/… - Ricky AH
4
[+29] [2010-02-23 04:24:29] Peter Pascale

Three projects aren't necessary (per James answer above). You can get POJO junit 4 tests to run in the Android test project without having the emulator running or device connected. I think the best practice is two projects - one for source, one for tests, and within tests, expect to have tests that are POJO (no android references/emulation required) and tests that require emulation.

But a catch (and a fix)... When I used the Eclipse Android Plugin to "Create a New Android Test Project", Eclipse wouldn't run the junit test with the junit test runner, it will only run them with the Android test runner on the emulator or attached device. Even after I created a new JUnit 4 test and eclipse added Junit 4 jar to the project.

The fix: Go to Run > Run Configurations... Select your Junit test case run config - the one that failed. To the left of Apply it will probably say "Using Eclipse JUnit Test Launcher - Select other...". Even though this seems right, it's not. Click Select other... and choose Android JUnit Test Launcher. Click Run and it should work. If it doesn't, right click on your test case and chose Run As... > JUnit Test. Thanks to Dan Syrstad for the tip.

I believe the initial run config should be Android JUnit Test, but that when you run you can select the JUnit Test config to not require emulation.

And be sure to connect your device for Android unit tests - its WAY faster than the emulator - no start-up time. Very easy to configure - see instructions here:

http://developer.android.com/guide/developing/device.html


(1) +1, awesome, now I can run just plain old tests :) - orip
+1 - this is exactly what I was looking for! - Kam Sheffield
(2) This is a bit old but just FYI at this time Android supports JUnit 3, which is why 4 might not work. "Note that the Android testing API supports JUnit 3 code style, but not JUnit 4." developer.android.com/tools/testing/… - pjco
5
[+25] [2009-02-11 04:05:46] James A Wilson

Working in android has helped me keep the separation of concerns in order. Keep as much logic out of the view as possible. Follow a common UI design pattern like MVC or MVP. Then that model logic can be unit tested with straight jUnit. I have three projects setup in eclipse.

  • One is the Android applications project.
  • The second is the test project where the view-dependent tests are run by adb
  • The third is where the standard JUnit tests are located.

This doesn't change the fact that using adb shell to run the Android tests is cumbersome. All I've been able to do is minimize the number of cumbersome tests.

As far as war stories: I was happy to figure out round trip testing the custom Parcelable [1].

[1] http://stuffikeepforgettinghowtodo.blogspot.com/2009/02/unit-test-your-custom-parcelable.html

6
[+24] [2011-06-03 04:12:36] Jeff Axelrod

For final integration testing, Robotium [1] is the way to go. However, for detailed coverage and very fast unit testing natively on the development PC (instead of the simulator or on real hardware,) I use PowerMock [2] to mock the Android objects.

I use this in conjunction with Infinitest [3] to enable automatic testing every time I save a file so I can get immediate feedback about whether I have broken anything.

Here's a sample of what my PowerMock unit tests look like:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ TextView.class, EditText.class, Editable.class, Toast.class})

public class NameWasEnteredTest {
    @Mock Context context;
    @Mock Editable editable;

    EditText firstName;
    EditText lastName;
    Button cancelButton;
    Toast toast;

    @Test
    public void simpleTest() {
        NameWasEntered.
               nameWasEntered(firstName, lastName, cancelButton, context);
        verifyThatFirstAndLastNameEditTextsAreCleared();
        verifyThatCancelButtonTextChangedToDone();
        verifyThatToastWasShown();
    }

    private void verifyThatCancelButtonTextChangedToDone() {
        verify(cancelButton).setText("Done");
    }

    private void verifyThatToastWasShown() {
        PowerMockito.verifyStatic();
        Toast.makeText(eq(context), eq("Name was entered"), anyInt());
    }

    private void verifyThatFirstAndLastNameEditTextsAreCleared() {
        verify(firstName).setText(null);
        verify(lastName).setText(null);
    }

    @Before 
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        firstName = PowerMockito.mock(EditText.class);
        lastName = PowerMockito.mock(EditText.class);
        cancelButton = PowerMockito.mock(Button.class);
        toast = PowerMockito.mock(Toast.class);
        PowerMockito.mockStatic(Toast.class);
        when(Toast.makeText(eq(context), anyString(), anyInt())).
               thenReturn(toast);
        when(firstName.getText()).thenReturn(editable);
        when(lastName.getText()).thenReturn(editable);
        when(editable.toString()).thenReturn("string");
    }
}

Related question [4].

[1] http://code.google.com/p/robotium/
[2] http://code.google.com/p/powermock/
[3] http://infinitest.github.com/
[4] http://stackoverflow.com/questions/3739737/attempt-to-stub-android-activity-class-using-powermockito-throws-runtimeexception

7
[+9] [2011-03-13 17:40:13] Paul Butcher

I recently released Borachio, a native Scala mocking framework which works on Android.

Because Borachio is written in Scala, you’ll need to write your tests in Scala. But it can be used to test code written in Java.

There's a description of how to use Borachio on Android on my blog:

http://www.paulbutcher.com/2011/03/mock-objects-on-android-with-borachio-part-1/ http://www.paulbutcher.com/2011/03/mock-objects-on-android-with-borachio-part-2/ http://www.paulbutcher.com/2011/03/mock-objects-on-android-with-borachio-part-3/


(4) +1 for "Android is the most test-hostile environment I’ve ever had the misfortune to find myself working in." - trdarr
8
[+7] [2009-02-06 21:51:22] Quintin Robinson

Aside from easily testing non platform dependent logic I haven't found a clever way to run tests, so far (at least for me) any actual platform logic testing is cumbersome. It's almost non trivial anyway because I've found differences in implementation between the emulator and my actual device and I hate to run a unit test implementation on my device just to remove the application afterwards.

My strategy has been: Try to be concise and make the logic well thought out and then test implementation piece by piece (less then desirable).


9
[+5] [2010-02-05 12:13:51] tichy

Anyone tried the Mockito [1] Framework in conjunction with android development? I always wanted to try it out. It is similar to EasyMock but doesn't depend on interfaces. It seems to create descending classes from your classes under test transparently. The only limitation I'm aware of is testing of final classes and function does not work...

[1] http://mockito.org/

(3) yes -- it doesn't work. It uses the cglib code generation library, which doesn't work with Dalvik. It also uses the Java Beans package which is not part of the Android framework. - Matthias
(3) Happy to say it does now. TDD can begin. :) - OceanLife
10
[+5] [2010-02-08 23:47:08] Jeremy Anderson

I found this presentation over at Slideshare [1] to be helpful.This combined with the blog post over at 8th Light [2] and looking at the unit test examples, scarce as they may be, in the API Demos app helped me to get started doing TDD on my Android app.

[1] http://www.slideshare.net/dtmilano/testing-on-android
[2] http://blog.8thlight.com/articles/2009/7/12/up-and-running-with-tdd-on-android

11
[+5] [2010-10-05 20:40:48] denis

Stephen Ng provides a good approach for real Unit Test for Android projects solution here:

https://sites.google.com/site/androiddevtesting/


(1) But I stuck to test WebVeiw with his android.jar. So I've wrote small parcer on Perl with regexp and made android.jar without any exception. It works fine for me. Hope it would be useful for somebody else. 4shared.com/get/KWwSl5an/android.html - denis
More details on problem solwing in my blog: denistimofeev.livejournal.com/3072.html - denis
12
[+5] [2010-11-30 10:35:31] OneWorld

I am fairly new to testing and found Hello, Testing [1] very helpful.

[1] http://developers.androidcn.com/resources/tutorials/testing/helloandroid_test.html

You link is 404 not found. - Gaurav Agarwal
13
[+1] [2009-08-03 03:13:44] Artem

I recommend using EasyMock extensively for unit testing. I recommend it highly -- the only problem is that somehow on Android (because of some Dalvik VM issues), it can only mock interface classes, and throws errors otherwise. We work around this by creating a TestableClass for every Class that we have, and making that class implement a mock interface that we can test against. I can describe more if people are interested.


(3) I'm interested in using EasyMock, would you care to elaborate on your workaround? What does your TestableClass look like? - Sarp Centel
14
[+1] [2010-05-02 08:02:00] Gubatron

Here's a ScreenCast I made on how I got Unit Tests to work. Simple Unit Tests and more complex unit tests that depend on having a reference to Context or Activity objects.

http://www.gubatron.com/blog/2010/05/02/how-to-do-unit-testing-on-android-with-eclipse/


15
[+1] [2010-11-29 18:30:11] Johan

You can also have a look at PowerMock [1] which extends EasyMock and Mockito and allows you to mock e.g. final classes and static methods as well as accessing internal state etc.

[1] http://code.google.com/p/powermock/

(2) PowerMock is great, but relies heavily on runtime byte code manipulation, so it won't work on Dalvik (still great for JVM tests tho, we use it, too). - Matthias
16