Join Chiu-Ki Chan for an in-depth discussion in this video Local vs. on-device, part of Effective Android Testing for Mobile Developers.
- [Female] The Android operating system is spelled using the Java programming language. When you write an Android app, you are using the Java core functionality with additional code provided by the Android operating system. Java is a widely used language, and the Java part of your app can be executed on any machine that runs a Java Virtual Machine, the JVM. This includes your computer, whether the is a desktop or a laptop.
However, to run and therefore test an Android app, you will need an Android device, either a physical one or an emulator. In either case, when you run your test, you will need to transfer your app and test code from the host computer to the device and install it. This takes time, therefore, it is genuinely desirable to organize your code such that you can compartmentalize the Java code, the part without any Android libraries into separate modules, and test them with JVM unit tests.
That is the fastest kind of test you can run, and it's a great way to test business logic code. But because the JVM does not have any knowledge about Android, JMV alone is not enough. To test Android specific code, you will need a way to run then on the device. This is called Instrumentation. In an Android project, JVM tests are located in the test folder, and Instrumentation tests are in the Android test folder.
There are two kinds of Instrumentation tests. Non-UI Instrumentation tests use Android classes, such as Asset Manager, SQLite Database, et cetera. It is slower than JVM unit tests because you need to deploy the app and the test code to a device. UI Instrumentation tests exercises visual UI componets, such as activity, text view, button, et cetera.
The test needs to simulate user actions such as typing, clicking, and scrolling. So additional to the time it takes to deploy code to the device, your test is going to take significantly longer to run through the UI. How do you decide which kind of test to run? When possible, write JVM Unit tests, because they are the fasted to run. But when you need access to an Android context, you will need to run it on device.
Since it takes time to simulate typing and clicking on the UI, try to structure your code so that you can first test the Non-UI component first. But eventually you will want to test your UI code. You can use Espresso to do that. Did you notice an empty box on our grid? Wouldn't it be nice if we can test the UI without waiting to send our code over to the device, install it, and then simulate all the typing and clicking? Indeed, people have tried that.
One way is to use the MVP, or Model View Presenter pattern. This is an architectural pattern that puts an interface in front of your Android UI code and pulls out all significant logic to the pure Java side of the interface in an object called the presenter. You write JVM Unit Test to test this Presenter and mark the interface representing the Android side.
This way you can test all the logic pertaining to changing and interacting with the Android UI via the interface without actually touching Android code, and thus can run everything on the JVM. Don't worry if this is overwhelming. In the next chapters, we will build an app together writing different kinds of tests along the way. We will start with the logic building the intelligence of the app and testing them with JVM Unit Tests and Instrumentation Unit Tests before writing the UI of the app and the associated UI tests.
You will see how to integrate testing as a part of your development process rather than an afterthought that you slap on at the end. Let's get started.
- Why test?
- Local vs. on-device
- Code coverage
- UI testing
- Hermetic environment
- Dependency injection
- Testing with MVP