I saw this Reddit discussion on Android testing concepts, which tries to categorize tests into short, medium and long. I don’t find that a very useful way to think about different types of tests, so I thought I’d give offer my view.
I think it’s more useful to think of tests in two dimensions
- Does it run on the JVM or needs a device?
- Does it test the UI or not?
Depending on the answer to these two questions you get 4 types of tests.
JVM tests are the faster to run since you don’t need to deploy to a device
(physical or emulator), and should be preferred. Try to structure your app so
that the logic is in pure Java classes i.e. does not use the Android framework.
Since we are writing Android apps, it is difficult to test the UI without the
Android framework. There are two ways you can do that.
The first way to test the UI on the JVM is Robolectric, which mocks the Android
framework. I don’t recommend that, because the mocked classes don’t necessarily
reflect the actual behavior on the Android framework.
The second way is to make your Android classes as logic-free as possible. There
are various architecture patterns you can use to achieve that, for an example
Model-View-Presenter (MVP). MVP allows you to encapsulate the Android part
inside the View (Activity or Fragment) and extract the logic into the Presenter,
which does not use any Android framework code. This way, you can test the
Presenter on the JVM.
After you have tested your logic extensively on the JVM (you may want to aim for
100% test coverage), you should add some UI tests. Think of these as sanity
checks, going through the happy path to make sure the app does not crash when
you bump up the library version. I use Espresso for UI tests, together with
Mockito and MockWebServer to set up a hermetic environment for repeatable tests.