1Overview

In this codelab, you'll learn how to set up your project in Android Studio for testing, write a Unit Test and run it locally on your development machine and also how to do functional UI testing on the device.

What you’ll learn

  • Updating the Gradle build files to include JUnit and the Android Testing Support Library
  • Writing Unit Tests which run on the Java VM on your local machine
  • Writing Espresso tests which run on the device or emulator

What you’ll need

2Create a new Android Studio project

If you’re launching Android Studio for the first time, select “Start a new Android Studio project” from the Welcome screen. If there’s already a project open, go to File > New > New Project…
The “Create new project” wizard will guide you through the process. On the first screen enter the following:
SettingValue
Application nameTestingExample
Company domaintesting.example.com
This will ensure your code has consistent naming with the content presented throughout the codelab. You can leave all the other selections on their default setting and simply press Next until your project is created.
You can press theRun button to check if the app runs correctly. You should either select and launch an Emulator from the list or make sure your device is properly attached via USB with debugging enabled.
The app doesn’t do much right now, but you should see a screen showing “Hello world!” and the name of 

3Configure your project for Unit test support

Before you start writing tests, let’s go through a short checklist to make sure that your project is configured correctly.

First, make sure you select “Unit Tests” under Test Artifact in the Build Variants pane.

Next, create the folders test and test/java under your module’s src folder. Note that you cannot do this using the default Android perspective. You can either use your system’s file explorer to create the necessary folders or switch to the Project perspective by using the drop down on the top-left of the Project pane. Your final project hierarchy should look like this:


(you can go back to the Android project perspective for the remainder of this codelab)
And lastly, open your module’s build.gradle (Module:app) file and add JUnit4 to your dependencies section, then click on the Gradle sync button.

build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.1.1'
    testCompile 'junit:junit:4.12'
}

4Create your first Unit Test

Now that everything is set up, it’s time to start writing your first test. But in order to do that, you will need some code that will be tested. For that purpose, let’s create a very simple Calculator class. This will be what is called our “class under test”.

We’ll add methods for the most common arithmetic operations, like addition and subtraction. Copy and paste the following code into your editor. Don’t worry about the actual implementations yet, just let all methods return 0 (zero) for now.

Calculator.java

package com.example.testing.testingexample;

public class Calculator {

    public double sum(double a, double b){
        return 0;
    }

    public double subtract(double a, double b){
        return 0;
    }

    public double divide(double a, double b){
        return 0;
    }

    public double multiply(double a, double b){
        return 0;
    }
}

Android Studio provides a quick way to create the actual test class for you. Just right click on the Calculator class declaration in your editor and select Go to > Test, then “Create a new test…

In the dialog window that opens, choose JUnit 4 and select the “setUp/@Before” option, as well as generate test methods for all of our calculator operations.

This should generate a test class skeleton in the correct folder (app/src/test/java/com/example/testing/testingexample) with the test methods ready to fill in. Here is an example of how you might test the calculator operations:

CalculatorTest.java

package com.example.testing.testingexample;

import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

public class CalculatorTest {

    private Calculator mCalculator;

    @Before
    public void setUp() throws Exception {
        mCalculator = new Calculator();
    }

    @Test
    public void testSum() throws Exception {
        //expected: 6, sum of 1 and 5
        assertEquals(6d, mCalculator.sum(1d, 5d), 0);
    }

    @Test
    public void testSubtract() throws Exception {
        assertEquals(1d, mCalculator.subtract(5d, 4d), 0);
    }

    @Test
    public void testDivide() throws Exception {
        assertEquals(4d, mCalculator.divide(20d, 5d), 0);
    }

    @Test
    public void testMultiply() throws Exception {
        assertEquals(10d, mCalculator.multiply(2d, 5d), 0);
    }
}
Feel free to copy the code to your editor or write your own tests using assertions provided by the JUnit framework.

5Running your tests

It’s finally time to run your test! Right click on the CalculatorTest class and select Run > CalculatorTest. You can also run the test from the command line, by issuing the following command in your project’s directory:
./gradlew test
Regardless of how you run your tests, you should see the output, telling you that 4 out of 4 tests have failed. This is the expected result, as we haven’t implemented the arithmetic operations yet.

Let’s modify the sum(double a, double b) method in the Calculator class to return a correct result and re-run the tests. You should see that only 3 out of 4 tests have failed.

Calculator.java

public double sum(double a, double b){
    return a + b;
}
As an exercise, you can implement the remaining methods to make all tests pass.

6Configure your project for instrumentation tests

Although there is support for running instrumentation tests in the Android framework, current development efforts are focused around the new AndroidJUnitRunner which is released as part of the Android Testing Support Library. The library also contains Espresso, a framework for running functional UI tests. Let’s add both to our project by editing the relevant sections in the module’s build.gradle file:

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.example.testing.testingexample"
        minSdkVersion 15
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"

        //ADD THIS LINE:
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    //ADD THESE LINES:
    packagingOptions {
        exclude 'LICENSE.txt'
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.0.0' //← MAKE SURE IT'S 22.0.0
    testCompile 'junit:junit:4.12'

    //ADD THESE LINES:
    androidTestCompile 'com.android.support.test:runner:0.2'
    androidTestCompile 'com.android.support.test:rules:0.2'
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1'
}
All that’s left is to switch to Android Instrumentation Tests in the Build Variants pane. Your project should sync automatically at this point. If it does not, press theGradle sync button.







7Add a simple interaction to your app


Before we begin testing the UI with Espresso tests, let’s add some Views and a simple behavior to the app. We’ll use an EditText where the user can enter his name and a Button that greets the user using the TextView for output. Openres/layout/activity_main.xml and paste the following code:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:text="@string/hello_world" android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <EditText
        android:hint="Enter your name here"
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Say hello!"
        android:layout_below="@+id/editText"
        android:onClick="sayHello"/>
</RelativeLayout>
You’ll also need to add the onClick handler in MainActivity.java:

MainActivity.java

public void sayHello(View v){
    TextView textView = (TextView) findViewById(R.id.textView);
    EditText editText = (EditText) findViewById(R.id.editText);
    textView.setText("Hello, " + editText.getText().toString() + "!");
}
You can now run the app to see it in action and make sure everything works properly. Before you press the Run button, make sure your Run Configuration is not set to run tests from the previous part of the codelab. Use the dropdown and select app. It should look like this: 

8Create and run an Espresso test


In the project overview, find your package name ending with the (androidTest) suffix and create a new Java class there. You can name it MainActivityInstrumentationTest. Paste the following code as its contents:

MainActivityInstrumentationTest.java

package com.example.testing.testingexample;

import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.action.ViewActions;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard;
import static android.support.test.espresso.action.ViewActions.typeText;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;

@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityInstrumentationTest {

    private static final String STRING_TO_BE_TYPED = "Peter";

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

    @Test
    public void sayHello(){
        onView(withId(R.id.editText)).perform(typeText(STRING_TO_BE_TYPED), closeSoftKeyboard()); //line 1

        onView(withText("Say hello!")).perform(click()); //line 2

        String expectedText = "Hello, " + STRING_TO_BE_TYPED + "!";
        onView(withId(R.id.textView)).check(matches(withText(expectedText))); //line 3
    }

}
The class will be run by the AndroidJUnitRunner and execute the test implemented in the sayHello() method. Here’s what the test does, line by line:
  1. First, it finds the view with the ID editText and types in the string “Peter”, then closes the on-screen keyboard.
  2. Next, the test performs a click on the View with text “Say hello!”. That’s our Button, for which we didn’t set an id in the layout XML, hence we refer to it by searching for its text.
  3. Finally, the text contents of the TextView are compared with the expected result and the test passes if they match.
You can run the test by right clicking on the class and selecting Run > MainActivityInstrume…  (the second one with the Android icon)

This will run your test on the emulator or connected device and, if you watch the screen, you can see the actions (like typing into the EditText) being performed by the runner. See the output in Android Studio for a report on passed and failed tests.

9Congratulations!

We hope you enjoyed the code lab and are excited to start testing your apps. What next?