19

I found great instrumental test tutorial on YT Advanced Android Espresso. I took code from there with small adjustment to my needs.

import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withChild;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withParent;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.core.AllOf.allOf;

...

@Test
public void checkToolbarTitle() {
    String toolbarTitile = getInstrumentation().getTargetContext().getString(R.string.my_bus_stops);
    onView(allOf(isAssignableFrom(TextView.class), withParent(isAssignableFrom(Toolbar.class)))).check(matches(withText(toolbarTitile)));
}

Unfortunatelly it does not work for me. Test failed with:

android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: (is assignable from class: class android.widget.TextView and has parent matching: is assignable from class: class android.widget.Toolbar)

What is wrong with it? How can I test it in other way?

shmakova
  • 6,076
  • 3
  • 28
  • 44

5 Answers5

33

This works for me:

onView(allOf(instanceOf(TextView.class), withParent(withId(R.id.toolbar))))
    .check(matches(withText("toolbarTitile")));
denys
  • 6,834
  • 3
  • 37
  • 36
  • 2
    This did not work for me. It was the import as Grzegorz Bielanski posted. instanceOf could not be resolved for me. – Brian S Mar 29 '17 at 17:37
  • Just wondering why are you down-voting?! It works for most of the cases (see amount of votes) and the fact that it doesn't work for you doesn't make this answer incorrect. – denys Mar 30 '17 at 13:01
  • How do I know it works for "most of the cases". My experience is that what works on Android changes from version to version, and a relevant answer today is not sure to be relevant tomorrow. – Brian S Jun 26 '17 at 16:42
  • @gr envoy How do you know that your experience and point are valuable for this answer? Just don't downvote if it doesn't work for you, leave a comment. You should appreciate people effort first. – denys Jan 08 '18 at 15:28
  • @denys I up voted this answer. This case worked for me. And I came across this answer when I was having a similar problem. And the fact that this answer still works more than a year on. Casts doubt on GR Envoy assumption that it could break tomorrow. – ant2009 Feb 03 '18 at 10:12
13

SOLUTION

The method is fine. As Chiu-Ki Chan wrote in her tutorial you can "pinpoint that one particular view". BUT you have to make sure you imported proper Toolbar:

import  android.support.v7.widget.Toolbar;

instead of:

import android.widget.Toolbar;
sunadorer
  • 3,855
  • 34
  • 42
13

Here's an alternative (and more idiomatic approach):

onView(withId(R.id.toolbar)).check(matches(hasDescendant(withText(toolbarTitle))))
Ugo
  • 587
  • 8
  • 12
7

If you're using an ActionBar, not a Toolbar, use this:

onView(allOf(instanceOf(TextView.class), 
     withParent(withResourceName("action_bar"))))
        .check(matches(withText("My ActionBar title")));

Note: To quickly add the imports for these methods, put the blinking cursor on the unresolved method, then do Android Studio ➔ HelpFind Action ➔ search for "show context action" or "show intention action" ➔ click on the result option ➔ A popup window will appear ➔ click on "Import static method ...". You can also assign a keyboard shortcut to "Show Context Actions". More info here. Another way is to enable "Add unambiguous imports on the fly" in the Settings.

Mr-IDE
  • 7,051
  • 1
  • 53
  • 59
6

I don't remember if I wrote this myself, or if I found it somewhere, but this is how I check toolbar titles:

public static Matcher<View> withToolbarTitle(CharSequence title) {
    return withToolbarTitle(is(title));
}

public static Matcher<View> withToolbarTitle(final Matcher<CharSequence> textMatcher) {
    return new BoundedMatcher<View, Toolbar>(Toolbar.class) {
        @Override
        public boolean matchesSafely(Toolbar toolbar) {
            return textMatcher.matches(toolbar.getTitle());
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("with toolbar title: ");
            textMatcher.describeTo(description);
        }
    };
}

This works with all cases. Example assertion: onView(withId(R.id.toolbar)).check(matches(withToolbarTitle("title")));

Jason Robinson
  • 31,005
  • 19
  • 77
  • 131