In this series of posts we are going to look at an Introduction to Automated Android Testing. In Part 1 of this automated testing series, we covered why you should write tests, where the test folders are located and the different types of tests you get in Android.

In this post, we are going to go over the typical structure and setup of your Android app in order to enable testing. I will be creating a simple app from scratch in this series and walk through each step of my thought process. The app we will be creating is a simple app that searches the Github API for users. Below is a rough mockup of what we will be creating:

We will be starting from scratch. If you follow the steps below, you should end up with the repository that looks like this.

Getting started with a new app

Open up Android Studio, select “Start a new Android Project”. Call the project “Gus” (Github User Search – original I know 😂) and company domain “riggaroo.co.za” . This will create a package name – za.co.riggaroo.gus . Click next. Next choose the versions of Android you wish to support (I generally don’t go lower than API 16. You will cover 95.2% of users if you choose API 16 and above). Select API version 16 and click “Next”. Select “Empty Activity” and click “Next”. Change the name of the activity to UserSearchActivity and the layout file to activity_user_search . Click “Finish”. If you run the app – you should see a blank activity like below.

Adding Test Dependencies

Navigate to your apps build.gradle file and add the following dependencies. The testing dependencies that need to be added include Espresso, Mockito, PowerMock and Hamcrest. Retrofit, OkHttp, RxJava and RxAndroid will also be added so we can do effective networking and achieve cleaner code.

compile 'com.squareup.okhttp3:logging-interceptor:3.4.0-RC1' compile 'com.android.support:appcompat-v7:24.1.1' compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha4' //Retrofit, RxJava and OkHttp. compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0' compile 'com.squareup.okhttp3:okhttp:3.4.0-RC1' compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' compile 'io.reactivex:rxandroid:1.2.1' compile 'io.reactivex:rxjava:1.1.6' compile 'com.squareup.picasso:picasso:2.5.2' //Dependencies for JUNit and unit tests. testCompile "junit:junit:4.12" testCompile "org.mockito:mockito-all:1.10.19" testCompile "org.hamcrest:hamcrest-all:1.3" testCompile("org.powermock:powermock-module-junit4:1.6.2") testCompile("org.powermock:powermock-api-mockito:1.6.2") testCompile 'com.squareup.okhttp3:mockwebserver:3.4.0-RC1' //Dependencies for Espresso androidTestCompile 'com.android.support:appcompat-v7:24.1.1' androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) androidTestCompile("com.android.support.test:runner:0.5") { exclude module: 'support-annotations' exclude module: 'support-v4' } androidTestCompile("com.android.support.test:rules:0.5") { exclude module: 'support-annotations' exclude module: 'support-v4' } androidTestCompile("com.android.support.test.espresso:espresso-intents:2.2.2") { exclude module: 'recyclerview-v7' exclude module: 'support-annotations' exclude module: 'support-v4' } androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.2.1') { exclude module: 'recyclerview-v7' exclude module: 'support-annotations' exclude module: 'support-v4' }

testCompile is the configuration for unit tests (located in src/test) and androidTestCompile is used for the instrumentation tests (located in src/androidTest). Differences between these two types of tests can be found in Part 1 of this series.

Using Gradle Build Flavors to enable Mocking

In order to enable easy and quick testing of the UI, we won’t be hitting the production APIs for Github. We will mock out responses and emulate different network responses. There are a couple of different ways to achieve this. The way in which I will demonstrate this is by using Gradle product flavors.

Flavors allow you to build different versions of your app, with some source code differences or resource differences. For instance, if you wanted to make a free version of your app and a paid version with more features, using product flavors would be a good way to achieve this.

In this instance, we will create a “Production” and a “Mock” flavor. We could also add a “Staging” flavour if we had a staging environment that we wanted our app to point to. This would allow us to install a production version of your app on a device at the same time as a mock version.

In order to use productFlavors , navigate to your app build.gradle file and add the following into the android{ } section. The following code means that for the mock variant, the applicationId will be different which means I can install both concurrently on one device. For the prod version, the applicationId will be taken from the defaultConfig setting. productFlavors { prod { } mock { applicationId "za.co.riggaroo.gus.mock" } } Invoke a Gradle Sync and then on the left hand side of your IDE, you should see a “Build Variants” tab. Open it to see the different flavors of your app that are now available.

If you select a different variant, when you click run the build that is deployed to your device will be using that variant’s source set and applicationId .

Running the Unit Tests

In order to run the default unit test (ExampleUnitTest) that exists within the project, you can do it in a few ways:

Within Android Studio navigate to and right click on the app/src/test/java folder. Click “Run Tests”.

folder. Click “Run Tests”. Using Gradle: in terminal you can run ./gradlew check

Running the Instrumentation Tests (Requires device or emulator)

In order to run the default instrumentation test (ExampleInstrumentationTest) that exists within the project, you can do it in the following ways:

Using Android Studio navigate to and right click on the app/src/androidTest/java folder. Click “Run All Tests”.

folder. Click “Run All Tests”. Using Gradle: in terminal you can run ./gradlew connectedAndroidTest

How to structure your code to enable easy testing

In order to enable easy testing I am going to use Dependency Injection. You can achieve this without any frameworks (which is what I mostly do) but a lot of people advocate for using Dagger 2 to achieve it. This blog post series is not going to use Dagger.

Create these classes in the following folder structure:

I have 4 top level folders for the different parts in the app. This can get more complicated the bigger your app gets. These are the basic folders I like to create:

presentation – Within this folder, I create subfolders and group functionality by feature. In this case, I created a folder called search which will hold the view and presenter for the search screen. It will also contain adapters and any other view related code for the search screen.

– Within this folder, I create subfolders and group functionality by feature. In this case, I created a folder called which will hold the view and presenter for the search screen. It will also contain adapters and any other view related code for the search screen. data – This will contain the repositories that will fetch data from the Github API.

– This will contain the repositories that will fetch data from the Github API. model – Contains the models that will be used on the presentation layer and the ones that come from the service calls.

– Contains the models that will be used on the presentation layer and the ones that come from the service calls. injection – Classes that will be used for Dependency Injection.

We have covered the setup of the sample app, how to run the different types of tests and the folder structure we will follow. This has now set us on a good path to ensure we can write tests for our app. If you want to see the result of this blog post, check out the corresponding completed code for this blog post here.

The next blog post in this series will go into detail about implementing the feature with tests. Don’t forget to subscribe so you don’t miss the next one!

Subscribe to Blog via Email

If you enjoy my posts, please consider buying me a cupcake to keep them coming.

[buy_cupcake]

Thanks to @JoshLiebe for proofreading this post.