Building on our knowledge of ADB, this guide focuses on automating UI tests on Android emulators. Automated UI tests ensure that your application’s user interface behaves as expected across different scenarios and devices.
Why Automate UI Tests?
Automated UI tests save time and resources by running tests that simulate user interactions. They help identify bugs and inconsistencies in the UI, providing a reliable way to maintain high-quality applications.
Setting Up Espresso for UI Testing
Add Dependencies
You need to add Espresso and other related dependencies in your build.gradle
file of your Android app module (app/build.gradle
).
defaultConfig {
//...
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Create a Test Class
In src/androidTest/java
and call it MainActivityTest
.
This test will ensure that the app is launched and ready for interaction. The test method will simulate a user clicking the plus button and verifies the resulting UI state.
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityTest {
@RunWith(AndroidJUnit4.class)
: This annotation tells JUnit to run the test class using the AndroidJUnit4 test runner. This runner provides compatibility with Android components and manages the test lifecycle.@LargeTest
: This annotation classifies the test as a “large” test. Large tests typically involve integration testing, where multiple components of the application are tested together.
@Rule
public ActivityScenarioRule activityRule =
new ActivityScenarioRule<>(MainActivity.class);
@Rule
public DisableAnimationsRule disableAnimationsRule = new DisableAnimationsRule();
@Rule
: Rules in JUnit are used to add or extend the behavior of each test method in a test class. They provide additional functionality before and after each test is run.ActivityScenarioRule<MainActivity> activityRule
: This rule launches the specified activity (MainActivity
in this case) before each test and closes it after each test. It provides a simplified way to test activities. TheActivityScenarioRule
starts and stops the activity and also ensures that the activity is running before the test begins.DisableAnimationsRule disableAnimationsRule
: This custom rule is used to disable system animations during the test run. Animations can interfere with Espresso tests by causing unexpected delays or timing issues, so disabling them ensures more consistent test results.
@Test
public void testClickPlusButton() throws InterruptedException {
// Click the plus button to open the AddEditTaskActivity
onView(withId(R.id.fab)).perform(click());
// Verify that the AddEditTaskActivity is displayed by checking for the presence of the title EditText
onView(withId(R.id.titleEditText)).check(matches(withText("")));
}
@Test
: This annotation indicates that the following method is a test method. JUnit will execute this method as a test case.public void testClickPlusButton()
: This is the test method. The method name typically describes what is being tested. In this case, it tests the behavior of clicking the plus button.onView(withId(R.id.fab)).perform(click());
: This line uses Espresso to interact with the UI. It finds a view with the IDfab
which is the floating action button in this app and performs a click action on it. Espresso’sonView
method is used to find views in the current activity’s layout, andperform
is used to execute actions on those views.onView(withId(R.id.titleEditText)).check(matches(withText("")));
: This line verifies that a view with the IDtitleEditText
is displayed and that its text is empty. This check is used to confirm that theAddEditTaskActivity
is displayed by looking for the presence of an empty titleEditText
. Thecheck
method is used to perform assertions on views, andmatches
verifies that the view’s state matches the specified condition.
@Test
public void testAddTask() throws InterruptedException {
// Click the plus button to open the AddEditTaskActivity
onView(withId(R.id.fab)).perform(click());
// Enter text into the title and description fields and close the keyboard
onView(withId(R.id.titleEditText)).perform(typeText("New Task Title"), closeSoftKeyboard());
onView(withId(R.id.descriptionEditText)).perform(typeText("New Task Description"), closeSoftKeyboard());
// Click the save button
onView(withId(R.id.saveButton)).perform(click());
// Verify that the new task is displayed
onView(withText(endsWith("New Task Title"))).check(matches(isDisplayed()));
}
@Test
public void testDeleteTask() throws InterruptedException {
// Delete the task
onView(withId(R.id.doneButton)).perform(click());
Thread.sleep(2000);
// Verify that the task is deleted by checking that the item is not in the list
onView(withText(endsWith("Task to Delete"))).check(doesNotExist());
Thread.sleep(2000);
}
Running UI Tests
Click on the green play icon next to the class definition to run all tests in the class. Alternatively, click on the green play icon next to individual test methods to run specific tests.
Viewing Test Results
-
Once the tests start running, the
Run
window will display the progress and results. -
The
Run
window shows which tests passed or failed, along with detailed logs and stack traces for any failures.
Analyze Test Results
- Green checkmarks indicate passed tests.
- Red X marks indicate failed tests, with details about the failure.
- Yellow warning signs indicate ignored or skipped tests.
Conclusion
Automating UI tests with Espresso provides a robust way to ensure your app’s user interface functions correctly. Next, we’ll explore performance testing on Android emulators, which is vital for optimizing your app’s performance. Proceed to Performance Testing on Android Emulators for more information.