Test-Driven Android: When and How I Use Robolectric

I’ll call this post “When and How I Use Robolectric” instead of “When and How to Use Robolectric” because a) I don’t like telling people when and how to do things, and b) I use Robolectric less liberally than most developers who use it.

Robolectric is a fantastic tool for ensuring that stuff in your Android app works properly. The problem, as you may have heard me say before, is that it runs slowly. In particular, FragmentTestUtil’s operations are especially time-expensive. Compounding the issue, Robolectric 3.0 currently has a memory leak that causes the heap to get bigger than it should. You won’t notice it on a smaller app, but when the app grows enough for the test suite to hit 600 or 700 Robolectric-assisted tests, the suite will hang or stop running because it runs out of memory before it completes.

So you only have 600-ish Robolectric bucks in the bank, and you spend one every time you write a test with Robolectric. My team at work, and I at home, have experimented with ways to save our Robolectric bucks. The first (main) trick has been to separate as much logic from the Android framework as possible and test that logic with JUnit. We save our precious Robolectric bucks this way, spending them on just a test or two for the places where the logic gets wired into the Android app.

Continue reading “Test-Driven Android: When and How I Use Robolectric”

Test-Driven Android: Testing Context-Dependent Components with a Provider

It’s much easier to write a test-driven application when we can isolate the class under test, so its tests fail as a result of its behavior and not the behavior of its dependencies. Exercising the dependencies in tests—whether they’re collaborating classes or entire frameworks—increases the number of reasons that a test might be failing, which limits how helpful that test can be in diagnosing issues and driving out an implementation.

In Android, there’s an additional concern: exercising the Android framework in tests is slow. So it makes sense to exercise the framework as little as possible in tests. This gets complicated when we consider the way the Android framework is built, though. First of all, it works chiefly by allowing us to subclass Android classes and override life cycle methods. This is not a recipe for easy dependency injection. Furthermore, idiosyncratic implementations of Android sometimes involve obtaining dependencies (like views from the layout) via a method besides injection. (We talk about how to test dependencies in that scenario in this post).

But there’s another catch to decoupling and testing in Android: the launching of some components depends on passing in other components.

Continue reading “Test-Driven Android: Testing Context-Dependent Components with a Provider”

Test-Driven Android: Separating Dagger from Robolectric in Test Suites

I test-drive Android apps with some help from the Robolectric testing framework. I also get some help (usually) from the Dagger dependency injector for employing dependency injection in those apps. I define modules in dagger for injecting classes into objects that depend on them, and I define test modules that inject mock versions of those classes when I write automated tests for the objects that depend on them.

As I learned more of the Robolectric and Dagger syntax over time, I could test-drive Android app features faster and faster. I did have an issue, though; in order to inject dependencies in Android, I needed a context. The Context object in Android provides information about the application environment, and it enables app-specific stuff like launching activities and sending/receiving broadcasts.

Continue reading “Test-Driven Android: Separating Dagger from Robolectric in Test Suites”