Introduction to Automated Android Testing – Part 6

In the previous 5 blog posts, we covered different aspects of building an Android app from scratch. We focused on including tests in the process. Here are the links to the previous posts:

  • Post #1 – Why should we write tests?
  • Post #2 – Set up your app for testing
  • Post #3 – Creating API calls
  • Post #4 – Creating repositories
  • Post #5 – Following the MVP pattern

In this last post of the series, we will cover creating Espresso tests for the View we created in part 5. The Github repo for this post can be found here.

Testing that a view contains the exact information expected can be tricky if the data is dynamic. This data can change at any time and our tests should not fail because of it. In order for the tests to be reliable and repeatable, we should not call any production APIs.

Mocking out the responses of the API calls will enable us to write tests that depend on the mocked data. There are a couple of ways in which we can mock out our API calls:

  • Option 1 – Use WireMock and run a standalone server which serves up the same static JSON for specific network calls.
  • Option 2 – Use OkHttp’s MockWebServer which runs a webserver on your device and serves up any response you request.
  • Option 3 – Create a custom implementation of the Retrofit REST interface that returns dummy objects.

Obviously, the choice is entirely up to you as to how you would want to go about writing UI tests. In my case, WireMock is extra effort as I would need to ensure I have a standalone server running with a static IP address.

MockWebServer is a lot easier to use than WireMock as you don’t have to set up a standalone web server (The server runs on the device). MockWebServer is also flexible because you can give it different scenarios. Useful features like specifying the failure rate of a certain call or simulating a slow network are possible using MockWebServer. (Read more here).

I am going to use option 3 for the purpose of testing that the UI matches the mock response data. If I wanted to add tests for slow network conditions (or some kind of non-functional test), I would choose option 2. If you are unable to use OkHttp,  I would choose option 1 as Wiremock works with any HTTP client.

Mocking out data using Gradle flavors

By making use of Gradle flavors, we can easily mock out of API responses.  If you read post #2 on Gradle flavors, you should already have a “mock” and a “production” flavor set up.

  1. Make sure you are switched to the mockDebug flavor. Select mockDebug variant
  2. Create a mock folder in the src directory. Then create a package within the mock folder, that mimics the main package name. Make a class called MockGithubUserRestServiceImpl. Your resulting file structure should look like this: Folder structure for mock testing
  3. Create a prod directory. Move the Injection class defined previously into this folder. We will be creating another Injection class in the mock folder. This class will inject the mocked out Github service instead of the production API. Move Injection to prod and create one in mock folderIn the Injection class that is located in the mock folder, we simply return the MockGithubUserServiceImpl that we created. In the prod folder, we return the actual Retrofit Github service. [adwords_square]
    Mock Injection class:

    Prod Injection class:
  4. The data returned from the mock service is dependant on your specific requirements. Below is my implementation of the MockGithubUserRestServiceImpl:

    In this case, I am just returning some dummy data. Let’s run the mock version of the app and we should get the same results no matter what you search.

    Android Test app with mock data

    Cool. Now we have a working dummy app! We can now write Espresso UI tests. [adwords_square]

Basics of Writing an Espresso Test

When writing an Espresso test, the following formula is used for performing functions within your UI:

  • ViewMatchers – Used to find a view in an activity. There are a bunch of different kinds of matchers. For example: withId(R.id.menu_search), withText("Search"), withTag("custom_tag") .
  • ViewActions – Used to interact with a view. For example: click(), doubleClick(), swipeUp(), typeText().
  • ViewAssertations – Used to make assertions that certain views possess specific properties. For example:   doesNotExist(), isAbove(), isBelow().

There is a great cheat sheet for the different Espresso methods that can be found in pdf form here: android-espresso-testing.pdf. It is worth mentioning that ordinary hamcrest matchers can be used when writing Espresso tests. Methods such as not(), allOf()  and anyOf() are valid.

Writing Espresso UI Tests

If you can recall, in post #2 we covered what dependencies will need to be added in order to write espresso tests. Now we will cover writing an Espresso test.

  1. Create a folder androidTestMock. The tests in this folder will only run on the mock variant and not on the production variant. Then make a directory that matches the main package name. In that directory, add a new class called  UserSearchActivityTest. Your project should then look like this:androidTestMock folder
  2. We will start by writing a basic test that ensures that when the activity is started, the text “Start typing to search” is displayed:

    The @Rule  ActivityTestRule specifies which activity this test will run with. In this case this test will run with UserSearchActivity. This will automatically start up the UserSearchActivity. Passing extra parameters will indicate if you want the activity to auto start or not.

    The test searchActivity_onLaunch_HintTextDisplayed() is quite simple. It searches in the view for the text and asserts that the text is visible on the UI.

  3. The next test is slightly more complicated:

    After typing into the SearchView and pressing enter, we assert that the dummy results are displayed on the UI.

  4. We have now written tests for the positive scenarios, we should add a test for the negative case too. We will need to adjust the MockGithubUserRestServiceImpl in order to allow it to return custom error observables if required.

    In the code above, a method was created in order to set a dummy observable for the search results. That observable will be returned if it is not null when searchGithubUsers() is called.

  5. Now we can create a test that checks if the error is displayed on the UI.

    In this test, we first ensure that the service will return an exception. Then we assert that the error message is displayed on the UI.

  6. Let’s run the tests:

Passing_UI_Tests

They all pass!

Code Coverage in Android

In order to know how effective your tests are, it is great to get code coverage metrics.

  1. To enable code coverage on your UI tests, add testCoverageEnabled = true  to your build.gradle:
  2. Run the task createMockDebugCoverageReport. You will then find the HTML report located here: app/build/reports/coverage/mock/debug/index.html.

Code Coverage Report in Android

Yay – we have 82% coverage just with the mock UI test. Taking into consideration the coverage reports we saw in post #4 and this post, it gives us a good indication of the test coverage of our entire app. Now we can iteratively go back and try cover more areas of our code.

PS – Code coverage currently doesn’t work with the Jack compiler. I switched to use Retrolambda in order to get the code coverage report to work. If you are interested in learning more, check out this branch.

Conclusion

We have finished writing our feature. Whew! 6 blog posts later. There is obviously a lot more testing that can be completed in this app. Non-functional tests such as testing how your app behaves on devices with low memory or with poor network connectivity can also be added.
That concludes the series on an “Introduction to Automated Android Testing”. I hope you enjoyed reading this series. If you enjoyed it, be sure to subscribe to the blog to receive future updates and share the post with your friends.

Further Reading

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.


If you would like to see more posts from me, please consider buying me a cupcake to keep them coming.

[buy_cupcake]


Introduction to Automated Android Testing – Part 5

In this series of blog posts, we are working through a sample app called Github User Search. Parts 1 – 4 covered why we should test, getting set up with testing, creating API calls and creating a presenter. Take a look at the previous posts as part 5 is a continuation of the series.

In part 5, we will take a look at interacting with the Presenter  created in part 4 and we will create the UI to display the list of search results.

Creating the UI

For the User Interface we want a simple list that displays the avatar, name and other user information in the list.

In part 4, we defined a View contract which the Activity should implement. This is where the Android specific code will be located (things such as visibility changes or any UI changes will be located here). To refresh your memory, this is the View contract we created in this last post:

Let’s implement the View! [adwords_square]

  1. Create a class called  UserSearchActivity. This class will implement the UserSearchContract.View contract and extend AppCompatActivity. Define a variable called userSearchPresenter of type UserSearchContract.Presenter. This is the object that we will interact with in order to perform our network calls.

    In onCreate(), create the presenter object. Provide it with the User repo defined in the Injection class. Pass the io() scheduler and the AndroidSchedulers.mainThread() scheduler so that the RxJava subscriptions know which threads they should perform their work on.

    On the next line, you can see I call userSearchPresenter.attachView(this) . This attaches the view to the presenter, so that the presenter can notify the view of any changes. Because the presenter isn’t aware of the activity’s lifecycle, in onDestroy() we need to inform the presenter that the view is no longer in existence, so we should then call userSearchPresenter.detachView(). This will unregister any RxJava subscriptions and prevent memory leaks from occurring.

  2. Create activity_user_search.xml in the layout folder. This will contain a RecyclerView, a ProgressBar, an error TextView and a Toolbar. I am using ConstraintLayout to design my screen, so I won’t go into too much detail as it is mostly drag and drop. (If you want to read more about ConstraintLayout check out my blog post about it here)UserSearchActivity

  3. We also need to add a SearchView to the toolbar so we have somewhere to type. Add a menu_user_search.xml file to the menu resource folder. Inside it, you will need to add a SearchView:

  4. We need to create a layout that will be used for each item in the RecyclerView. Create a file named list_item_user.xml in the layout folder. I used ConstraintLayout with one ImageView for the avatar and two TextViews.List_item_user_designmode

  5. Now that we have all the layouts we need, let’s tie the XML to the Activity. First, in onCreate() we will get references to the views we need.

  6. We need to hook the SearchView up into our activity to make it trigger the presenters search() method. In the onCreateOptionsMenu(), add the following code:

    This will inflate the correct menu, find the search view and set a query text listener. In this case, only when someone presses submit on the keyboard, we will respond by calling the search presenter with the query. We could do it in onQueryTextChange too but due to rate limiting on the Github API I will stick to onQueryTextSubmit. By default, the item will be expanded.[adwords_square]

  7. Next, we will implement the callbacks that the presenter will call when the items are finished loading.

    We are basically just toggling visibility of views here and setting the usersAdapter  to the new items that the service returned.

  8. For completeness, here is the UserSearchAdapter class which is used for the RecyclerView on the activity:

     

    Injection class

  9. Now if you run the app, you should be able to search for a username on Github and see results.github_user_search

Yay! We have a working app. Code for this post can be found here. In the next part, we will look at writing UI tests for the app. Make sure you subscribe so you don’t miss a post!

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.


If you enjoyed this blog post, please consider buying me a cupcake to support future blog posts.

[buy_cupcake]

Introduction to Automated Android Testing – Part 2 – Setup

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:

Android Automated Testing Sample App

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

Getting started with a new app

  1. Open up Android Studio, select “Start a new Android Project”.
  2. 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.Step1 Automated Android Test Project
  3. 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”. Step 2 Automated Android Test Project
  4. Select “Empty Activity” and click “Next”.Step 3 Automated Test Project Android
  5. Change the name of the activity to UserSearchActivity  and the layout file to activity_user_search. Click “Finish”.Step 4 Naming default user activity.
  6. If you run the app – you should see a blank activity like below.Step 4 Blank App

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.

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.

  1. 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.
  2. 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. Gradle Build Variants Android Studio

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 .

[adwords_square]

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”.Running Unit Tests with JUnit in Android Studio
  • 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”.Run connected tests android studio
  • 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:Simple Structure Of Android App

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.
  • data – 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.
  • 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

Enter your email address to subscribe to this blog and receive notifications of new posts by 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.

Introduction to Automated Android Testing – Part 1

I’ve seen a lot of people confused and unsure about how to do tests in Android. In the past, it was very difficult to test Android apps and there wasn’t much direction. In this series, I am going to try make testing a bit easier for you. This first post is just to get you started with testing, the next few will go more in depth into testing in Android. Let’s get started!

Android Testing

Why should I test anyway?

You probably don’t really need convincing, since you are already reading this blog post. Here are some reasons why I like to write tests:

  • Testing forces you to think in a different way and implicitly makes your code cleaner in the process.
  • You feel more confident about your code if it has tests.
  • Shiny green status bars and cool reports detailing how much of your code is covered are both consequences of writing tests.
  • Regression testing is made a lot easier, as automated tests would pick up the bugs first.

Regression testing is the biggest benefit for me. If you refactor and your tests still pass, you will be confident that you haven’t broken anything. The problem with testing is that you might not see the benefit of testing immediately, as the true value will only surface a couple of months later when you need to refactor.

What types of testing are there in Android?

Unit Testing

A unit test generally exercises the functionality of the smallest possible unit of code (which could be a method, class, or component) in a repeatable way.

Tools that are used to do this testing:

  • JUnit – normal test assertions.
  • Mockito – mocking out other classes that are not under test.
  • PowerMock – mocking out static classes such as Android Environment  class etc.

UI Testing – Instrumentation Tests

A UI Test or Instrumentation Test mocks typical user interactions with your app. Clicking on buttons, typing in text are some of the things UI Tests can complete.

Tools that are used to do this testing:

  • Espresso –  Used for testing within your app, selecting items, making sure something is visible. 
  • UIAutomator – Used for testing interaction between different apps.

There are other tools that are available for this kind of testing such as RobotiumAppiumCalabashRobolectric

What do I need to get started with Automated Testing?

In order for you to get started with automated testing in your app, you should follow some kind of architectural pattern that will help you test and structure your app in a clean, testable way. One such pattern that easily enables testing is Model View Presenter (MVP) for Views and Repository Pattern for Networking and Database Access.

Of course, this is not the only option for you as an Android Developer, it is one of the many that you can explore in order to get test coverage and a clean architecture.


I have found it very difficult to implement tests without having a defined structure, often my tests were useless and I didn’t know what to test, it was also very difficult to get code coverage on large apps. My UI tests were also not very reliable as they were testing against production servers. Hopefully we can address these issues in this blog series.

Structure your App in a Testable Way

Here is a diagram depicting the structure I will use as a guideline for the rest of the blog post series:

Basic Structure Of Android App that will allow for Automated Testing

  • Views  – Activities and Fragments. This is where we set text and make UI changes. I typically like to keep the Android specific code in this section and try not to pass a context further than the view, obviously this is not always easy but it is good guidance to try follow. Views should only talk to presenters.
  • Presenters – This is where business logic to decide what should be displayed on the views is going to go.  Presenters talk to the repositories to get information out, and convey information to the Views. Try avoid putting Android specific code in your presenter if you can avoid it as it will make unit testing more difficult.
  • Repositories – Decide where to get data from, should they come from local persisted data? Or should the data come from the network? Repositories talk to presenters.
  • Models – Typically POJOs, these are models that are used by the Presenter and the View to convey information to the View from the Presenter.

Unit tests will test the Presenters and the Repositories. UI Tests will test the View all the way down to the repositories.



There are many great articles describing MVP and other architecture options – this blog post is not going to go into those details. Read more about different Android architectures here, here and here.

Where are Automated Tests placed in my Android app?

In your Android app folder structure, there are two folders that will house the tests:  test  and androidTest

Automated testing in Android

androidTest  – Android Instrumentation Tests are located here. The tests in this folder need to run on an Android Emulator or physical device.

test/ – Unit tests are placed in this folder. Unit Tests run on the JVM on your local machine and do not run on an Android device or emulator. This means they do not have access to Android classes (such as the Context  class).


Now that we are aware of the different kinds of tests and where to place in them in our apps. The next post we will go deeper into how to structure your code in order to allow for better unit testing. Check out Part 2 here!

Make sure you get notified about the rest of the series by subscribing to updates.

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Retrofit 2 – Mocking HTTP Responses

In the previous post, I discussed implementing a custom Retrofit Client to mock out different HTTP response codes. This mechanism works well for Retrofit versions 1.9 and below but has its drawbacks. After trying out Retrofit 2, I have adjusted the previous sample and managed to achieve the same results (with some improvements 😀).

In order to test your android apps, one thing that normally gets frequently overlooked is the apps ability to handle different server responses. What if your server goes down for a while? Does your app fall over with it – or does it gracefully recover? Things like this are difficult to emulate with real servers, which is why mocking responses is such a great way to ensure your app is awesome.

In this example, we will look at creating an app that retrieves a quote of the day from a web service and displays it to the user. We will also add a failure mechanism to the front end to show the user a retry button if something goes wrong. We will also look at testing these failure mechanisms.


Example 1:

  1. Create a Rest Service interface that will be used with Retrofit.
  2. Ensure your activity calls the Retrofit Service that you have just created. In the code below, the service gets created and the activity asynchronously calls getQuoteOfTheDay() . When a successful response is received from the server, the quote is displayed otherwise a retry button is shown with an error message.
  3. You might wonder, how do we test that the retry button is properly shown when the server is down without turning the server off? 😁 Using Espresso and Retrofit MockWebServer we can easily achieve this. Create mock JSON and store it in your androidTest  folder.
    Success Response Sample JSON:

    404 Not Found Sample JSON:
  4. Below is the sample for testing the positive case (a quote is displayed to the user) and the negative case. A retry button is displayed to the user when the server is returning an error. You might want to do some other logic when there is an error but for simplicity we will just display a retry button.

    From the sample above, we can see that the method setUp() is starting up the MockWebServer and setting the BASE_URL  of the entire app to point to the local mock server’s url.
    The test testQuoteIsShown()  is enqueuing a 200 OK response on the mock server, with the JSON from the file we defined previously as the body. We then launch the Activity. Using Espresso, we ensure that the retry button is hidden and the quote is displayed.
    The test testRetryButtonShowsWhenError() does a similar thing, except it queues up a 404 response, ensures that the retry button is shown and that the text “Quote Not Found” is displayed.
  5. As you can see from the above sample, we have achieved the same results as the previous post, but using Retrofit 2.

Pros of testing this way:

  • Really simple to test different HTTP Status Codes
  • Not much code needed to emulate the different responses

Cons of testing this way:

  • Difficult to dynamically create the responses

Example 2:

In the sample app, I have also included another way to test your Rest API by implementing the interface defined at the very beginning.

  1. Create a mock implementation of your API methods. In this stub, we create a dummy quote and return that quote every time. This is defined in the androidTest folder.

    2. Create another mock implementation that will return the error scenario.

3. Create a test which will test the API response parsing.

As you can see, the implementation that we mocked out previously is now being used in the test. In the  setUp()  method the MockRetrofit object is created. This MockRetrofit object wraps around the dummy implementation that we created and emulates a network call by adding delays onto the calls.



The testRandomQuoteRetrieval()  uses the first mock implementation to test the positive scenarios, whereas  testFailedQuoteRetrieval()  uses the second mock implementation which will return a 404 error.

This can be used to test operations on the API and test front end scenarios such as adding items to the server without sending it off to the server unnecessarily.

Pros of testing this way:

  • Can create rich data to return to the tests which means testing can be more meaningful
  • Easy enough to set up
  • JSON isn’t static

Cons:

  • Have to create new API implementations for different error scenarios
  • Hard to see from a glance what the API returns

I think a combination of the two mechanisms described above can definitely cover most scenarios that you would need to test in order to make your app stable. What are your thoughts?

You can check out the full project here on Github.


If you enjoyed this blog post – please consider buying me a cupcake!

No. of Cupcakes