Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Espresso vs Actionbar

I have been trying to test an app that has a menu drawer using Espresso.

Now for the strangeness.

In the first test, I open the drawer and click on an item then proceed with the rest of the test. That all works great.

When I add a second test that does the exact same thing, I get an exception. It appears to be something related to content of the menu drawer but I am at a loss.

The exception is this:

com.google.android.apps.common.testing.ui.espresso.PerformException: Error performing 'single click' on view '(with id: is <2131099739> and with text: is "Events")'.
at com.google.android.apps.common.testing.ui.espresso.PerformException$Builder.build(PerformException.java:67)
at com.google.android.apps.common.testing.ui.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:57)
at com.google.android.apps.common.testing.ui.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:40)
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction.runSynchronouslyOnUiThread(ViewInteraction.java:146)
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction.doPerform(ViewInteraction.java:77)
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction.perform(ViewInteraction.java:69)
at com.xxx.app.events.StackOverflowExampleTest.selectMenu(StackOverflowExampleTest.java:83)
at com.xxx.app.events.StackOverflowExampleTest.setUp(StackOverflowExampleTest.java:72)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:192)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:177)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at com.google.android.apps.common.testing.testrunner.GoogleInstrumentationTestRunner.onStart(GoogleInstrumentationTestRunner.java:119)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1608)
Caused by: java.lang.RuntimeException: Action will not be performed because the target view does not match one or more of the following constraints:
at least 90 percent of the view's area is displayed to the user.
Target view: "TextView{id=2131099739, res-name=menu_item_content, visibility=VISIBLE, width=432, height=112, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=24.0, y=2.0, text=Events, input-type=0, ime-target=false}"
at com.google.android.apps.common.testing.ui.espresso.ViewInteraction$1.run(ViewInteraction.java:100)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
at java.util.concurrent.FutureTask.run(FutureTask.java:137)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4898)
at java.lang.reflect.Method.invokeNative(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
at dalvik.system.NativeStart.main(Native Method)

And here is the test class

public class StackOverflowExampleTest extends ActivityInstrumentationTestCase2<MainActivity_>
{
    public StackOverflowExampleTest()
    {
        super(MainActivity_.class);
    }

    /**
     * Basic check for content displayed
     */
    @SuppressWarnings("unchecked")
    public void testSanityCheck()
    {
        // check title is shown
        onView(allOf(withId(R.id.event_view_title), isDisplayed())).check(
                        matches(withText("Isaac Vladimir Sinead Stacey"))); //$NON-NLS-1$

        // check content is shown
        onView(allOf(withId(R.id.event_view_text), isDisplayed())).check(
                        matches(withText(startsWith("Arcu ipsumcurabitur. Aliquammauris sodalessed arcu.")))); //$NON-NLS-1$

        // check "more details" is shown
        onView(allOf(withId(R.id.event_view_link), isDisplayed()))
                        .check(matches(withText(R.string.events_button_text)));
    }

    /**
     * Basic check for content displayed
     */
    @SuppressWarnings("unchecked")
    public void testSanityCheck2()
    {
        // check title is shown
        onView(allOf(withId(R.id.event_view_title), isDisplayed())).check(
                        matches(withText("Isaac Vladimir Sinead Stacey"))); //$NON-NLS-1$

        // check content is shown
        onView(allOf(withId(R.id.event_view_text), isDisplayed())).check(
                        matches(withText(startsWith("Arcu ipsumcurabitur. Aliquammauris sodalessed arcu.")))); //$NON-NLS-1$

        // check "more details" is shown
        onView(allOf(withId(R.id.event_view_link), isDisplayed()))
                        .check(matches(withText(R.string.events_button_text)));
    }

    @Override
    protected void setUp() throws Exception
    {
        super.setUp();

        // start the activity
        this.getActivity();

        // show events fragment
        this.selectMenu(R.string.menu_item_events);
    }

    @SuppressWarnings("unchecked")
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    protected void selectMenu(final int menuItemResId)
    {
        // open the drawer
        onView(withId(android.R.id.home)).perform(click());

        // click the supplied menu item (aka list item)
        onView(allOf(withId(R.id.menu_item_content), withText(this.getActivity().getString(menuItemResId)))).perform(
                        click());

    }
}
like image 510
Corey Scott Avatar asked Dec 04 '22 08:12

Corey Scott


2 Answers

I had the same issue when the view you are going to operate on is not visible on the screen or visible partially. So if you have problem with some view on screen - just scroll to it and then click:

onView(withId(is(R.id.button_login))).perform(
    scrollTo(), 
    click());

If you have this problem in drawer which has a list of items and you want to click at item which is not visible - use onData(...). But you have to show drawer before (see how to open drawer here):

onData(is(instanceOf(com.your.package.SomeDrawerItem.class)))
    .inAdapterView(withId(R.id.drawer_listview))
    .atPosition(itemPositionInDrawer).perform(click());
like image 153
denys Avatar answered Jan 12 '23 19:01

denys


It looks like view in the drawer is not visible yet. You could maybe try to assert the visibility of the view before performing any action on it :

assertTrue(withEffectiveVisibility(Visibility.VISIBLE).matches(myView));
assertFalse(withEffectiveVisibility(Visibility.VISIBLE).matches(myView));
like image 28
Snicolas Avatar answered Jan 12 '23 17:01

Snicolas