What is unit testing in android

Android Testing part 1: Unit testing 0 to 1

Nov 16, 2017 · 5 min read

Part 1: This article

Better Android unit testing with MVVM

This is continuation of my series on Android Testing:

Espresso tests from 0 to 1

This is part 3 of my series of articles on Android testing.

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

The 3 types of tests in Android Testing

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 f or 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 😀 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?

Читайте также:  Проверить андроид по imei коду

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

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:

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

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

Here comes the Presenter:

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 😀

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.

Источник

Learn Unit Testing in Android by building a sample application

In the last article, I listed out the benefits of Unit Testing your applications. In this tutorial, we’ll take a look at how to begin Unit Testing your Android Applications.

If you haven’t checked out the previous article on why you should unit test your android app, then you must take a quick look at it before moving ahead with this one.

Let’s get started!!

Install the dependencies

Place these dependencies in your app level build.gradle file:

  • Junit: It is a “Unit Testing” framework for Java Applications. It is an automation framework for Unit as well as UI Testing. It contains annotations such as @Test, @Before, @After etc.
  • Mockito: Mockito mocks (or fakes) the dependencies required by the class being tested. It provides annotations such as @Mock.
Читайте также:  Бета тестирование что это такое андроид

Create a sample app:

Unit Tests are generally written before writing the actual application. But for the sake of explanation in this article, I am creating a sample app before writing Unit Tests.

Unit Testing is done to ensure that the developer would be unable to write low quality/erroneous code. It makes sense to write Unit Tests before writing the actual app as then you wouldn’t have a bias towards the success of your tests, you will write tests beforehand and the actual code will have to adhere to the design guidelines laid out by the test.

Now, lets create our sample app.

We’ll be creating a simple app, whose sole purpose would be to get user data from input fields and save it using in a shared preference file.

First things first, here is the code for activity_main.xml layout file:

Now, here is the code for MainActivity.java:

Now try and run the app. I should display a screen like this:

Upon entering the name, DOB and email address and clicking on save, the details will be saved to a shared preference file.

Writing Unit Tests:

Now, let’s write some Unit Tests.

We’ll be Unit Testing the following classes:

Navigate to: app/java/com(test) and expand all the folders under com(test).

Create a new java file and name it EmailValidatorTest.java

Here we will be testing our EmailValidator class. We have to come up with all the input cases we can think of. What all can the user enter in the email input field:

  1. Correct Input: test@gmail.com
  2. Email with subdomain: test@gmail.co.uk
  3. Without .com: test@gmail
  4. With extra characters: test@gmail..com
  5. With no username: @gmail.com
  6. Empty Input:
  7. Null value: this can occur if we initialize the string from this field to be null. It doesn’t hurt to have a test case for null check in place.

While the 1st and the 2nd test cases must pass, rest of the inputs are invalid and hence the tests must fail. Let’s write the tests for all of them:

Test Cases

2. Email with subdomain

4. With extra characters:

5. With no username:

7. Null value check:

While most of the code is self-explanatory, here are some things you might not know:

  • @Test: @Test is an annotation provided by JUnit Framework for marking a method as a test case. As you can see here, each method is a test case testing the input field for a possible input. This instructs the compiler to consider the method as a test case in the test suit.
  • assertTrue(): assertTrue is a method provided by Junit Framework to assert (force) the value inside it’s parentheses as TRUE. If the value inside the parentheses evaluates to be false, the test case fails.
  • assertFalse(): Same as the assertTrue method except that it asserts the argument inside the parentheses to be false instead of true. If the passed parameter is true, the test case fails.

Here is the complete EmailValidatorTest.java class:

And Voila!! You have written your very first Unit Test. It is as simple as that.

Most of the apps you develop will have much more complicated functionality than this but it is the perfect place to start learning about Annotations, methods provided by the Junit framework for unit testing.

Читайте также:  Как восстановить данные вацап андроид

But so far, we have used only the Junit framework, now let’s dive into what Mockito does.

Mockito

Mockito is a JAVA library that is used for Unit Testing the Java applications. It is used to mock the interfaces so that dummy objects can be created and used to provide the dependencies for the class being tested.

Let’s look at how it’s done.

In our test folder (where you created EmailValidatorTest.java), create another file named SharedPreferencesHelperTest.java

We’ll be testing the SharedPreferencesHelper class now. Here is the code:

Take a look at all the mock annotations. The SharedPreferencesHelper class takes in a SharedPreference in its constructor. It needs that argument to function properly, so we create a mock/dummy instance of SharedPreferences using the @Mock annotation.

Notice that we are creating two instances of SharedPreferences, one is a normal mock and other is a broken mock. These are basically just two test cases. In the first one, the preferences work as expected and data is written to the file successfully, but, in the second mock, we are testing for the failure of writing the data.

Unsuccessful write of data on sharedPreference can occur due to various reasons such as providing the wrong key, wrong context etc.

Annotations

Here you encounter three new annotations:

  • @Mock: As explained above, it creates a dummy object needed by the class to be tested to function properly.
  • @Before: This annotation is used to mark any method to run before executing the test cases. Here we initialize mSharedPreferenceEntry, mMockSharedPreferencesHelper, mMockBrokenSharedPreferencesHelper.
  • @RunWith: It instructs the IDE to initialize the Mockito library. An alternative to this would be writing MockitoAnnotations.initMocks( testClass ) in the @Before method.

Any un-annotated method works just as a normal method

JUnit methods:

You encounter 3 new methods provided by JUnit Framework:

  • assertThat(): As is evident by the name, this method lets you create custom assertions and not just true and false values. It takes in 3 arguments. A reason/description, input value to be checked, expected actual value.
  • Is(): Is method returns a Matcher to match the source object to the one provided as the parameter of is();
  • equalTo(): As the name suggests, this method checks for equality between the expected and actual value.
  • When(): This is a very powerful method which takes in a method call as its parameter. It takes in the method call which is to be stubbed/duplicated. Once the method stub is executed, “then()” is called.
  • thenReturn(): It is called after the method stub provided in when() method has finished running. It is used to return the result of the method, if it is not void.

We have written tests to ensure that any broken shared preferences should not be able to write/read from the brokenSharedPreferencesFile. Another test case to ensure that a proper(unbroken) sharedPreferencesHelper can write to the preferences successfully.

And this is how you write Unit Tests for your android app. We have tested 2 standalone classes, SharedPreferencesHelper and EmailValidator for correctness in all the test cases.

Here is a final roadmap to create a unit test (it can be more elaborate, but for a beginner, this would suffice):

  1. Think of all the possible test cases.
  2. Create a method for each test case and annotate it with @Test
  3. Create a @Before method and initialize the Mockito library.
  4. Write your test cases using methods such as when, is, assertThat/False/True etc.

Источник

Оцените статью