Android Testing part 1: Unit testing 0 to 1

Eric N
AndroidPub
Published in
5 min readNov 16, 2017
Dat f*cking success!

Part 1: This article

You have been developing Android apps for a couple of years. You want to start writing tests for but unsure how to start?

Rejoice, this tutorial is here to the rescue!

Make no mistake, the first step is the hardest. I know because I’ve recently gone “from 0 to 1" in unit testing. Now I want you to embark on this fantastic journey and enjoy the success with me.

The important questions

Why write tests?

  • Improve and maintain product quality with less QA’s manual effort
  • Increase confidence when shipping
  • Perform routine checks humans can’t perform, fast
  • Help you write better code

Why unit tests first?

  • Fast to run
  • Easy to write, run and measure coverage

Ok, we want to start unit test our code, how do we start?

  • Step 1: Refactor your code from MVC (Model-View-Controller — reads “everything in Activity”) to MVP (Model-View-Presenter — easiest to start with; testing the ViewModel in MVVM (Model-View-ViewModel) is the same as testing the Presenter in MVP, refactoring takes more effort though). That is, separate your (testable) app logics from Android specific (difficult-to-test) stuffs like Activity and Fragment.
  • Step 2: Write tests! And run tests (and measure test coverage) and profit :)

You’ll only need to remember 1 thing:

separate your (testable) app logics from Android specific (difficult-to-test) stuffs

Read more about MVP architecture here

The app

The app developed for this tutorial is GitHub Search. I assume that everyone here uses GitHub. Isn’t it awesome that this app let you search all the repositories on GitHub?

This app is definitely not “Foo bar” or “Hello World” kind of app. It’s not bloated with stuffs like RxJava (which you should learn in a separate tutorial) either.

The code

master branch contains MVC code. This is your starting point now and my starting point a year ago (No shame there :D Our apps work fine and our bosses are happy right?)

step-1-mvp branch contains the code after refactoring to MVP. Refactoring your code to MVP (or MVVM + data binding in a later part) separates your testable logics from stuffs that contains little to zero logic, platform specific and very difficult to test such as Activity and Fragment.

step-2-unit-tests branch contains the tests you all been waiting for. These tests may be humble but don’t all great things have small beginnings?

Getting from no unit tests to having some proper unit tests is tough. You’ll be writing hundreds and thousands of tests in no time. What could be more exciting than getting your test coverage increase week by week? Just imagine how proud you would be showing your unit testing success to your fellow Android engineers and employers.

From MVC to MVP

Our big fat MainActivity in its “glorious” MVC form

MVC Activity

Our Activity is huge (~70 lines for our very simple screen) this way and the logics are not testable!

Let’s move the logics to its own place, namely the Presenter (and test it yay)!

But first, let establish the contract between the View (our MainActivity) and the Presenter (SearchPresenter) through 2 interfaces:

SearchPresenterContract

defines what the Presenter do — searchGitHubRepos() in this case

public interface SearchPresenterContract {
void searchGitHubRepos(String searchQuery);
}

SearchViewContract

defines what the View do: displaySearchResults() and displayError()

public interface SearchViewContract {
void displaySearchResults(@NonNull List<SearchResult> searchResults);

void displayError();

void displayError(String s);
}

Here comes the Presenter:

Presenter in MVP

The “repository” here is the essence of the Data Layer in MVP Architecture. Technically, I’m presenting to you a simplified version of MVP Architecture here. It’s necessary to introduce the repositories in our projects to avoid bloating our presenters — multiple presenters can share the same repository and 1 presenter can call multiple repositories e.g. GitHub repositories, Twitter repositories (for users to follow the authors of the popular GitHub repos for example)

Look at our MainActivity! It’s so much slimmer (~40 lines vs. original ~70 lines), so much cleaner now :D

Write your first unit tests

Unit tests are supposed to be isolated. Therefore, in each test we only want to test 1 class. We need to either stub or mock the external dependencies.

For example, in our SearchPresenterTest (testing SearchPresenter logics), we will mock the Repository and ViewContract here.

When possible, use stubs as they execute faster compared to mocks.

Test the Presenter:

Run your (unit) tests with Android Studio

Right click on the test class or package and select “Run ‘Tests in ‘packagename’’ with coverage” (Coverage is optional of course)

Won’t you look at those green stuffs of satisfaction and 😄? There are nothing quite like the moment you run your tests and they all pass!

Conclusion

The automated testing journey starts here. After reading my article, the hardest part is already over. Now, you should have no excuse to procrastinate your duty to write tests.

I can’t promise writing unit tests will always be easy but I promise it’s going to be worth it.

Any comments, questions or suggestions are welcome. I’ve got a lot more to learn about unit testing Android apps so let’s help each other to improve.

Next Steps

Dependency Injection with Dagger

More about Android architectures

For a succinct but clear comparison MVC vs. MVP vs. MVVM checkout Eric Maxwell’s article ;)

P.S. Robolectric and 100% test coverage?

Once you have moved all the logics out of your activities, fragments and views, you can optionally use Robolectric to unit tests those Android-specific classes to achieve 100%. I wouldn’t worry about that until I have perfected your app architectures and tested all your presenters, models and viewmodels though.

Q & A?

Ask me any question in a “Reply”. You can even show your “glorious” code in a snippet or GitHub repo and ask me how to refactor and test your code ;)

--

--