Loading...

"The solution often turns out more beautiful than the puzzle."

Arushi Pant

Always eager to learn. Determined to make the best of the time I've got on Earth.

Espresso: Click on AdapterView list item with a specific text content

Posted on August 14, 2018

I just started learning how to write Instrumentation tests with Espresso. This learning is a part of my Android Developer Nanodegree[1] offered by Udacity & Google.

The content in the Nanodegree is a good start, but I decided to take my learning a step further when I was solving their practice exercise. 

 

The problem statement was to write a test that would click on a GridView tea item, and check that it opens up the corresponding tea OrderActivity.

Tea Time project in Udacity-Google nanodegree

Picture Credit: Udacity

 

The case with AdapterViews is that the item you need to interact with may not have been loaded yet. The data is loaded dynamically from an Adapter, and only a subset of the contents will be loaded into the current view hierarchy at a given time.

This is why we need to use onData() instead of onView() to get the item we need. 

If you really just want to solve this problem, you can just get an item by position, click on it, and check the name displayed in the next activity.

@Test
    public void clickGridViewItem_OpensOrderActivity() {
        String teaName = "Chamomile Tea";
        onData(is(instanceOf(Tea.class)))
                .atPosition(5)
                .perform(click());
        onView(withId(R.id.tea_name_text_view))
                .check(matches(withText(teaName)));

    }

 

In the above code, I ask my test to go to the 6th position item of the list (program will scroll to make the item visible), click on the item, and then check that name of the tea displayed in the next Activity is as expected. And this is how they explain the solution to the problem. It is the most basic way we can solve the problem statement. 

But, what if I do not know the position of this item I want to get clicked. I only know the Tea Name displayed for the item in the list. How would I find this item then? 

It took me some time to solve this question, and understand the solution, as I was not getting a good explanation online for my query.

To click on an item according to the content of the item, we need to write a Matcher method. Tea is the type of item we have in our Adapter data List, and the matcher will use the getTeaName() getter method of the Tea object to check whether the object is the one with the content (teaName) we want.

private static Matcher<Tea> teaHasName(final String teaName) {
        return new TypeSafeMatcher<Tea>() {
            @Override
            public void describeTo(Description description) {
                description.appendText("with name: " + teaName);
            }

            @Override
            protected boolean matchesSafely(Tea item) {
                return item.getTeaName().equals(teaName);
            }
        };
 }

 

Now, we can now use this matcher to get our item with onData(). The code will be as below.

 @Test
    public void clickGridViewItem_OpensOrderActivity() {
        String teaName = "Chamomile Tea";
        onData(teaHasName(teaName))
                .perform(click());
        onView(withId(R.id.tea_name_text_view))
                .check(matches(withText(teaName)));

    }

 

 

[1] Referral link - Will give you a Rs. 1000 cashback on your first Nanodegree enrollment


Liked the post?

Show your appreciation, and share with others.