ANDROID UI TESTING USING ESPRESSO:
UI testing can be done by a human tester performing a set of user operations on the Application and verify that it is behaving as expected. Main problem with this approach is that it is time consuming, tedious and error-prone. Instead, we can use automated approach to simulate user actions on the application easily in a repeatable manner.
-
test code is written inside (src/androidTest/java) folder. ( same folder we have used for Instrumented Unit Tests here ).
-
Create one new class AutomatedUiTest.java inside this folder..
-
For testing android applications, we can have two different types of automated UI tests :
-
Test for single app : This type of test is performed to check only the test application .
-
Test for multiple apps : This type of test is performed to test the behaviour of interactions between test application and other user applications and/or between system applications. e.g. we are developing a camera application and we want to check if it can share photo to other photo viewer application or not.
-
Android Testing Support Library includes a testing framework called Espresso that we can use to write UI tests for devices with Android 2.2 and higher. Espresso works with AndroidJUnitRunner test runner .
SETUP :
include the following dependency to your build.gradle file :
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.1'
Espresso has 3 components :
-
Find view we want to test in an Activity : By calling onView() method or if you are using AdapterView , use onData() method.
-
Perform Action : ViewInteraction and DataInteraction object is returned for onView() and onData() method. we can call perform() method on these objects to pass a user action .
-
Verify result : Use ViewInteraction.check() method to check a view state.
e.g :
onView(withId(R.id.id_view)).perform(click()).check(matches(isDisplayed()));
Example :
In this tutorial, we will create one simple login page, input username and password and finally click on the “login” button. One text view will be used to display success or failure.
- Update your activity_main.xml file as below :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#303F9F"
android:focusable="true"
android:focusableInTouchMode="true"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<android.support.design.widget.TextInputLayout
android:id="@+id/layout_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColorHint="#B2EBF2">
<EditText
android:id="@+id/editTextEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="email"
android:inputType="textEmailAddress"
android:textColor="#E0F7FA" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/layout_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/layout_email"
android:textColorHint="#B2EBF2"
>
<EditText
android:id="@+id/editTextPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="45dp"
android:hint="password"
android:inputType="textPassword"
android:textColor="#E0F7FA" />
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/layout_email"
android:layout_marginTop="104dp"
android:background="#00BCD4"
android:text="Login"
android:textColor="#E0F7FA" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="text"
android:layout_below="@+id/button"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:textColor="#E0F7FA"
android:id="@+id/textViewResult" />
</RelativeLayout>
- Add the following to your MainActivity.java
mLoginButton = (Button) findViewById(R.id.button);
mEmailET = (EditText) findViewById(R.id.editTextEmail);
mPasswordET = (EditText) findViewById(R.id.editTextPassword);
mResultTV = (TextView) findViewById(R.id.textViewResult);
mLoginButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mEmailET.getText().toString().equals("codevscolor@gmail.com") && mPasswordET.getText().toString().equals("password"))
mResultTV.setText("success");
else
mResultTV.setText("failed");
}
});
}
- Update AutomatedUITest.java as :
import android.support.test.filters.LargeTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
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.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 AutomatedUITest {
private String mEmail;
private String mPassword;
private String mSuccessMsg;
@Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(
MainActivity.class);
@Before
public void initUserNamePassword() {
mEmail = "codevscolor@gmail.com";
mPassword = "password";
mSuccessMsg = "success1";
}
@Test
public void login_MainActivity() {
onView(withId(R.id.editTextEmail))
.perform(typeText(mEmail));
onView(withId(R.id.editTextPassword)).perform(typeText(mPassword));
onView(withId(R.id.button)).perform(click());
// Check if the result is success or not
onView(withId(R.id.textViewResult))
.check(matches(withText(mSuccessMsg)));
}
}
Here , we are using ActivityTestRule to write this test. Using this, the testing framework will launch the activity before each test method (@Test), Before test, it will run @Before method, and after test is completed, it will run @After and shut down the Activity.
To run this test, right click on “AutomatedUITest” -> Run “AutomatedUITest” -> select device or emulator and click OK.
This sample project is shared on Github.