Android

Testing Androd Apps

android testing unit test instrumentation test
Written by Yasir Ameen

It is very important part to test your Android apps before it is released to publicly.  You can verify correctness, functional bevahiour and usabiliy of your app. You dont want your public audience to submit bad feedback about your product. In this tutorial i will take you to the deep knowledge about testing your Android app using Android Studio.

Testing Types

Android studio provides two ways of testing your apps.  Local Unit Tests  and Instrumented Tests. Android Studio also provides source code directories for Local Unit Testing and Instrumented Test.

  1. Local Unit Tests -> These tests require only JVM and do not need any Android Framework.
  2. Instrumented Tests -> These tests run on phycial Android device or an Android emulator.

 

testing android app unit test insturmet test

Above image is the basic understanding about Android testing lets understand more about concept.

 

What are both testing and thier difference?

So at this point we need to understand more about testing. Some termonology is very hard to understand but with the following you can understand very clear concept about testing in Android

unit test instrumen test

Writing Simple Unit Test

Create a simple class in your project and name it, “SimpleMathLogic” and wirte following fuctions, these are the funtions we will test in this simple Unit Test.

 public class SimpleMathLogic {

    public int add(int a, int b) {

        return  a+b;
    }

    public int product(int a, int b) {

        return  a*b;
    }

    //Following fuction will check if the string is palindrome
    public boolean isPalindrome(String word){

        int i,j;
        for(i = 0, j = word.length()-1; i <= word.length()/2; i++, j--) {

            if(word.charAt(i) == word.charAt(j)) {
                continue;
            }
            return false;
        }

        return true;
    }
}

Ok now its time to write test class. Create a class in your unit-test package (as i show you in above image) and name the class “SimpleMathLogicTest” it is a good practice to call your call by its mirror name, in my case SimpleMathLogic is my class and SimpleMathLogicTest is Test class.

Note : When you write test methods in your test class, dont forget to add @Test annotation above method name.

 


import org.junit.Assert;
import org.junit.Test;

public class SimpleMathLogicTest {

    @Test
    public void testAdd() {

        //Following snippet of code will check if 4 + 6 is 10, otherwise test will fail;
        SimpleMathLogic logic = new SimpleMathLogic();
        int sum = logic.add(4,6);
        Assert.assertEquals(10,sum);
    }

    @Test
    public void testDiff() {
        //Following snippet of code will check if 4 * 6 is 24, otherwise test will fail;
        SimpleMathLogic logic = new SimpleMathLogic();
        int sum = logic.product(4,6);
        Assert.assertEquals(24,sum);
    }

    @Test
    public void testchecker(){

        //Following snippet of code will check if text is palindrome, otherwise test will fail;
        SimpleMathLogic logic = new SimpleMathLogic();
        boolean result = logic.isPalindrome("KAYAK");
        //Here i am using override method of asserEquals(errortext,expected, result)
        Assert.assertEquals("Input text is not a palindrome",true,result);
    }
}

Running a Simple Test

Now its time to run the test and see the results. Running a unit test is very easy just right click on your test class file and select Run SimpleMathLogicTest or just click Ctrl+Shift+F10.

 

running a unit test jUnit

 

Showing Test Results

When you run unit tests, you see its result in Run Window at the bottom. In this window you can see how many test you tested and how many tests are pass and failed along with the details of each test.

android unit test junit

 

Writing Unit Test Beyound The Basic

At this point you have got pretty much idea about Unit Testing, Let’s wirte a Unit test with some addition information we can put in Unit Test.

Unit Test Annotation

Annotation provide more meaning to our functions or method about how should it behave. You can use following annotions in your test class.

  1. @Before => You initialize objects and any other data you want to you use during each test method.
  2. @After    =>  You frees up your resources you used in your test and cleans up after each test method.
  3. @BeforeClass => This annotation method runs before testing all the test methods in your class.
  4. @AfterClass   =>  This annotation method runs after testing all the test mothods in your class.
  5. @Ignore => You sometimes want to specific test methods in your class and rest of you ignore.

I have modified our SimpleMathLogicTest class according to the annotations i discussed above. Here is the modified code.


  public class SimpleMathLogicTest {

    private SimpleMathLogic logic;

    @BeforeClass
    public static void testclassStartUp() {
        
        System.out.println("Starting all the test methods of SimpleMathLogicTest Class");
    }

    @Before
    public void setup() {

        logic = new SimpleMathLogic();
        System.out.println("Initializing Simple Math Test");
    }

    @Test
    public void testAdd() {

        //Following snippet of code will check if 4 + 6 is 10, otherwise test will fail;
        int sum = logic.add(4,6);
        Assert.assertEquals(10,sum);
    }

    @Test
    @Ignore
    public void testDiff() {
        //Following snippet of code will check if 4 * 6 is 24, otherwise test will fail;
        int sum = logic.product(4,6);
        Assert.assertEquals(24,sum);
    }

    @Test
    public void testchecker(){

        //Following snippet of code will check if text is palindrome, otherwise test will fail;
        boolean result = logic.isPalindrome("KAYAK");
        //Here i am using override method of asserEquals(errortext,expected, result)
        Assert.assertEquals("Input text is not a palindrome",true,result);
    }

    @After
    public void WrapUp() {

        System.out.println("Done Testing With Simple Math Test");
    }

    @AfterClass
    public static void testclassWrapUp() {

        System.out.println("Done all the test methods of SimpleMathLogicTest Class");
    }

}

Here is the result of above test class, keep in mind that there is one test method is ignore, so its icon changed.

android test unit testing junit annotaions

 

Unit Testing With Hamcrest.

When you write tests class, you check its results with assertion there are number of assertion funtions available to check its passed or not, you can see the assertion list here. But when you want to test your methods over some conditions or with complex unit test with good feature then you use Hamcrest.

Note : In order to use Hamcrest you will to add following dependency in your build.gradle(Module.app) file

 testCompile 'org.hamcrest:hamcrest-library:1.3

Ok now it’s time to write some test using Hamcrest, create a class in your unit test package and name it UnitTestWithHamcrest  and write the following test methods.

 

  public class UnitTestWithHamcrest {


    //This is the test with Built-In unit test assertion methods.
    @Test
    public void testWithAsserts() {
        List<String> list = getProgrammingList();
        assertTrue(list.contains("C#"));
        assertTrue(list.contains("PHP"));
        assertTrue(list.size() > 3);
        assertTrue(list.size() < 12);
    }

    //This is the test with Built-In unit test assertion methods.
    @Test
    public void testWithBigAssert() {
        List<String> list = getProgrammingList();
        assertTrue(list.contains("PHP") && list.contains("C++") && list.size() > 3 && list.size() < 12);
    }

    //This is the test with Hamcrest, testing same functionality as in testWithAsserts() method.
    //You can compare both the tests with code.
    //Hamcrest also provide better error easy to read and understand why test fail.
    @Test
    public void testWithHamcrest() {
        List<String> list = getProgrammingList();
        assertThat(list, (hasItems("C#", "PHP")));
        assertThat(list, allOf(hasSize(greaterThan(3)), hasSize(lessThan(12))));
    }


    //This test will fail because there is no programming XYZ
    @Test
    public void testFailureWithAsserts() {
        List<String> list = getProgrammingList();
        assertTrue(list.contains("PHP"));
        assertTrue(list.contains("XYZ"));
        assertTrue(list.size() > 3);
        assertTrue(list.size() < 12);
    }

    //This test will fail because there is no programming XYZ
    //But this will provide more readable error
    @Test
    public void testFailureWithHamcrest() {
        List<String> list = getProgrammingList();
        assertThat(list, (hasItems("PHP", "XYZ")));
        assertThat(list, allOf(hasSize(greaterThan(3)), hasSize(lessThan(12))));
    }


    private List<String> getProgrammingList() {
        String[] sentence = {"Java", "C#", "PHP", "Swift", "Html", "JavaScript", "Css", "Objective-C", "C++"};
        return Arrays.asList(sentence);
    }
}

Examining Hamcrest Test Results

In you see in below image that there are 5 tests run and 2 fails, but the important thing i want to mention here is that Hamcrest giving you enough information about you test, why its fails and the actual values.

android unit test junit hamcrest

Now that’s all for now fo Unit Testing. You can learn more about unit test from the developer site.

————————————————————————————————————————————

Writing Instrumentation Tests

It’s time to boot up your device or start an emulator because we are going to learn Android Instrumentation test. There are numbers of test you can run as Instrumentation test with some of built-in capabilites and with some additional thier party libraries.

1) Writing  Test Using Android Testing Support Library Rules

You use Android support library Rules to trigger the creation of Android elements like Activity and Services, you will need add dependcies in your build.gradle file in order use these rules in your Instumentaion test.

following is my project dependcies you can comapre with it.

 dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.1.1'
    testCompile 'org.hamcrest:hamcrest-library:1.3'
    androidTestCompile 'com.android.support.test:runner:0.5'
    androidTestCompile 'com.android.support.test:rules:0.5'
    testCompile 'junit:junit:4.12'
}

Create a class in your android Instrumentation Test package, in my case I am testing for MainActivity.java, so i wll call it MainActivityTest.java and write the code look like mine.

In this test i am testing two UI components the TextView and a Button.

My activity_main.xml file look like below.


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="app.yasirameen.androidtesting.MainActivity">

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello Test!" />

    <Button
        android:text="Click Me!"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/text_view"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="20dp"
        android:id="@+id/btn_test" />
</RelativeLayout>

and MainActivity.java file is look like below


@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

    @Rule
    public ActivityTestRule<MainActivity> mainActivityActivityTestRule = new
            ActivityTestRule<>(MainActivity.class);
    
    Activity activity;
    TextView _txtview;
    Button _btn_test;

    @Before
    public void setupComponents(){

        activity = mainActivityActivityTestRule.getActivity();
        _txtview = (TextView) activity.findViewById(R.id.text_view);
        _btn_test = (Button) activity.findViewById(R.id.btn_test);
    }

    @Test
    public void testTextView() {
        assertNotNull(activity.findViewById(R.id.text_view));
        assertTrue(_txtview.isShown());
        assertEquals("Hello Test!",_txtview.getText().toString());
    }

    @Test
    public void testButton() {

        assertNotNull(activity.findViewById(R.id.btn_test));
        assertTrue(_btn_test.isShown());
        assertTrue(_btn_test.isClickable());
    }

    @After
    public void WrapUp(){

        System.out.println("Done Test");
    }
}

Running Instrumentation is similar like running unit test by right clicking on MainActivityTest.java class and click Run MainActivityTest.java although you will need to run this test on a real device or an emulator. Run the test and you will the result if every goes fine.

android test instrumentation junit

 

Testing Apps Using  Available Test Tools

 

Testing With UIAutomator

In this test I am going to tell you about the UIAutomator test, using test you can test various funtionality. These are key points of UiAutomator Test.

  1. ApIs to do do black box testing.
  2. Test interactions with other apps
  3. Test interactions with device buttons like on/off and back/home button and other.
  4. Provide Viewer to inspects UI Layout and Properties of Android Apps.
  5. UiAutomator Provide UiDevice class which represents device or emulator.
  6. UidDevice class represents method like, pressBack(),  pressHome(), pressMenu(), setOreintation() etc.

androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'

In the following example I am testing my MainActivity (see Test Above) . In order to test with UiAutomator you will need following libary in your build.gradle

 


@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

    @Rule
    public ActivityTestRule<MainActivity> mainActivityActivityTestRule = new
            ActivityTestRule<>(MainActivity.class);

    @Before
    public void setupComponents(){

        System.out.println("Components Initialize");
    }

    @Test
    public void testBackKeyPress(){

        getInstance(InstrumentationRegistry.getInstrumentation()).pressBack();
    }


    @Test
    public void testUi() throws RemoteException{

      UiDevice device =  UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
      if(device.isScreenOn()){
          device.setOrientationLeft();
          device.openNotification();
          device.openQuickSettings();
          device.pressHome();
      }
    }

    @Test
    public void testComplexUI() throws RemoteException{

        UiDevice device =  UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
        if(device.isScreenOn()) {

            device.openNotification();
            device.pressBack();
            device.openQuickSettings();
            device.freezeRotation();
            device.setOrientationLeft();
            device.setOrientationRight();
            device.pressBack();
            device.pressHome();
        }
    }

    @After
    public void WrapUp(){

        System.out.println("Done Test");
    }
}

See how this test works (Video)

 

Inspecting UI Elements Using UiAutomator

With UiAutomator you can inspect UI Elements of your app and others app. This is very good tool for understanding how UI Elements properties and other info. Here is the video how you can start UiAutomator Inspector.

How To Start Inspect Tool : Open your command prompt and type uiautomatorviewer.bat under your Android-sdk/tools directory.

 

————————————————————————————————————————————————————–

Android UI Testing With Espresso

Espresso provide Faster UI Test. Using Espresso you can test your Apps UI. You test your app using Express by Finding a Element you want to test then interact with functions provide Espresso and check the result. Espress provide Matcher and Viewer for testing.

You will need following libary in order to test with Espresso.


androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'

I am not going to deep here, but just giving general idea how this test is perform, further more you can visit Espresso for understanding more about Espresso.


@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

    @Rule
    public ActivityTestRule<MainActivity> mainActivityActivityTestRule = new
            ActivityTestRule<>(MainActivity.class);

    @Before
    public void setupComponents(){

        System.out.println("Components Initialize");
    }

    @Test
    public void greeterSaysHello() {
        onView(withId(R.id.txt_name))
                .perform(typeText("Yasir Ameen"));
        onView(withId(R.id.say_hellp0))
                .perform(click());
        onView(withText("Hello Yasir Ameen!"))
                .check(matches(isDisplayed()));
    }

    @After
    public void WrapUp(){

        System.out.println("Done Test");
    }
}

 

Here is the cheat sheet of Android Espress Test, with that you will get to know more features.

androdi espresso testing ui test

 

———————————————————————————————————————————————————

Android Performance Monitor

Android Performance Monitor helps you to visualize various aspects of your app, you can monitor Memory, CPU and GPU usage by the app. You can also monitor network traffic (Network traffic will only be seen in real device). You can see real time information about your app.

Starting Android Perfomance Monitor:

  1. Run your app in debug mode.
  2. Click View from the menu then => Tool Windows => Android Monitor
  3. You will see two tabs in Monitor Tools 1) LogCat and other is Monitor.

 

android testing unit test

 

There more testing tools availble which you can use for testing your apps, but for now i am ending here 🙂

About the author

Yasir Ameen

I'm a programmer, teacher, and speaker. I work out of my home in Pakistan, Karachi for the Mobile, especially Android Platform. I discuss about technology, gadgets, codes, the devices we’re going and we’ve been. I’m excited about community, social equity, and media.

Leave a Comment