Running tests on an Android emulator or device is slow! Building, deploying, and launching the app often takes a minute or more. That’s no way to do TDD. There must be a better way.
Wouldn’t it be nice to run your Android tests directly from inside your IDE? Perhaps you’ve tried, and been thwarted by the dreaded 'java.lang.RuntimeException: Stub!'
?
Robolectric is a unit test framework that de-fangs the Android SDK jar so you can test-drive the development of your Android app. Tests run inside the JVM on your workstation in seconds. With Robolectric you can write tests like this:
// Test class for MyActivity
@RunWith(RobolectricTestRunner.class)
public class MyActivityTest {
private Activity activity;
private Button pressMeButton;
private TextView results;
@Before
public void setUp() throws Exception {
activity = new MyActivity();
activity.onCreate(null);
pressMeButton = (Button) activity.findViewById(R.id.press_me_button);
results = (TextView) activity.findViewById(R.id.results_text_view);
}
@Test
public void shouldUpdateResultsWhenButtonIsClicked() throws Exception {
pressMeButton.performClick();
String resultsText = results.getText().toString();
assertThat(resultsText, equalTo("Testing Android Rocks!"));
}
}
Robolectric makes this possible by intercepting the loading of the Android classes and rewriting the method bodies. Robolectric re-defines Android methods so they return null (or 0, false, etc.), or if provided Robolectric will forward method calls to shadow Android objects giving the Android SDK behavior. Robolectric provides a large number of shadow objects covering much of what a typical application would need to test-drive the business logic and functionality of your application. Coverage of the SDK is improving every day.
Robolectric handles inflation of views, string resource lookups, etc. Some view attributes (id, visibility enabled, text, checked, and src) are parsed and applied to inflated views. Activity and View #findViewById()
methods return Android view objects. Support exists for include
and merge
tags. These features allow tests access resources and to assert on view state.
Run your tests on your workstation, or on your Continuous Integration environment. Because tests run on your workstation in a JVM and not in the emulator Android runtime, the dexing, packaging, and installation on the emulator steps are not necessary, allowing you to iterate quickly and refactor your code with confidence.
An alternate approach to Robolectric is to use mock frameworks such as Mockito or Android Mock to mock out the Android SDK. While this is a valid approach, we have found that without Robolectric, the level of mocking needed to test an Android app quickly yields tests that are essentially reverse implementations of the application code.
Robolectric allows a test style that is closer to black box testing, making the tests more effective for refactoring and allowing the tests to focus on the behavior of the application instead of the implementation of Android. You can still use a mocking framework along with Robolectric if you like.
We welcome contributions. Please fork and submit pull requests. Don’t forget to include tests!
Look at the sample project to see how fast and easy it can be to test drive the development of Android applications.
Google Group: http://groups.google.com/group/robolectric
Group Email: [email protected]
Samples: http://github.com/pivotal/RobolectricSample