Get started with App testing using Espresso
Espresso is used to write concise and reliable Android UI Automation Test cases. To make best use of Espresso, one should be familiar with the codebase under test. One of the important features in Espresso is that it automatically synchronizes your test actions with the user interface of your application.
Benefits of Espresso
- Small Core API, leading to ease in learning
- Faster test execution
- Actions and assertions happen when UI is at rest due to which waits, syncs, sleeps, and polls are not required
The main components of Espresso include the following:
- Espresso — Entry point to interact with views (via onView() and onData()). Also exposes APIs that are not necessarily tied to any view, such as pressBack().
- ViewMatchers — A collection of objects that implement the Matcher<? super View> interface. You can pass one or more of these to the onView() method to locate a view within the current view hierarchy.
- ViewActions — A collection of ViewAction objects that can be passed to the ViewInteraction.perform() method, such as click().
- ViewAssertions — A collection of ViewAssertion objects that can be passed the ViewInteraction.check() method. Most of the time, you will use the matches assertion, which uses a View matcher to assert the state of the currently selected view.
Lets get started on writing first test with Espresso
Step 1: Create a new project in Android Studio
- Open Android Studio and Create a new Project
- Select Login Activity and click on Next
3. Enter name of the project and click on Finish button
4. Let gradle build task complete
Step 2: Add Espresso dependencies
Once the gradle task is complete and project is loaded, Open your app’s build.gradle file. This is usually not the top-level build.gradle file but app/build.gradle and Add the following lines inside dependencies:
androidTestImplementation ‘androidx.test.espresso:espresso-core:3.4.0’androidTestImplementation ‘androidx.test:runner:1.4.0’androidTestImplementation ‘androidx.test:rules:1.4.0’
Step 3: Set the instrumentation runner
Add below line to the same build.gradle file in android.defaultConfig:
testInstrumentationRunner = “androidx.test.runner.AndroidJUnitRunner”
Updated build.gradle would look like as below and Sync you project to use the added dependencies
plugins {
id 'com.android.application'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.example.espressodemologin"
minSdk 21
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.annotation:annotation:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation 'androidx.test:runner:1.4.0'
}
Step 4: Add new test
Android Studio creates tests by default in src/androidTest/java/com.example.espressodemologin/
- Create a new java class in the folder specified above
- Name it as ‘LoginInstrumentedTest’
- Add @RunWith(AndroidJUnit4.class) at the top of the class
- Add Rule inside class to perform test on Login Activity
@Rulepublic ActivityScenarioRule<LoginActivity> activityRule =new ActivityScenarioRule<>(LoginActivity.class);
5. Add Test in the test class as below
@Test
public void loginTest() {
onView(withId(R.id.username)).check(matches(isDisplayed()));
onView(withId(R.id.username)).perform(ViewActions.typeText("username@gg.com")).check(matches(withText("username@gg.com")));
onView(withId(R.id.password)).perform(ViewActions.typeText("password")).check(matches(withText("password")));
onView(withId(R.id.login)).perform(ViewActions.click());
}
6. Import all required packages/classes
Complete test should look like as below
package com.example.espressodemologin;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.*;
import androidx.test.espresso.action.ViewActions;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.example.espressodemologin.ui.login.LoginActivity;
@RunWith(AndroidJUnit4.class)
public class LoginInstrumentedTest {
@Rule
public ActivityScenarioRule<LoginActivity> activityRule =
new ActivityScenarioRule<>(LoginActivity.class);
@Test
public void loginTest() {
onView(withId(R.id.username)).check(matches(isDisplayed()));
onView(withId(R.id.username)).perform(ViewActions.typeText("username@gg.com")).check(matches(withText("username@gg.com")));
onView(withId(R.id.password)).perform(ViewActions.typeText("password")).check(matches(withText("password")));
onView(withId(R.id.login)).perform(ViewActions.click());
}
}
Step 5: Run the test
You may now run the test by clicking on run icon for test or class
Step 6: View execution report
Once tests are executed, report is created under app/build/reports/androidTests/connected folder.
index.html file contains result for all the tests. Open this file in a browser to view the report.
In the next blog, we will write more tests and talk about how to create custom matchers to assert toast message.
Happy Testing!!