jeudi 22 septembre 2016

Espresso testing NestedScrollView - "Error performing 'scroll to' on view 'with id:"

Firstly, I have looked at several other posts that seem to have a similar problem.

I have followed: Android espresso NestedScrollView, how to scroll to bottom

Now I get the forementioned error, and found this post: Scrolling to view was attempted, but the view is not displayed

I have no padding in my NestedScrollView - I even tried removing padding from the XML alltogether, for testing purposes, but it made no difference.

I am now writing to you guys, in hopes of finding a solution!

In short: I need to scroll down through my NestedScrollView in order to test my xml file with Espresso. This is my test(So far it is not supposed to do anything, but scroll down):

    @Test
    public void testScrollDownAbilityOfDetailsScrollView(){
        goToSpecificItemOnStream(streamItemWithOneImage);

        onView(withId(R.id.end_of_details))
                .perform(ScrollToAction.betterScrollTo());

    }

It uses a custom made Scroll To Action class:

    public final class ScrollToAction implements ViewAction {

    private static final String TAG = ScrollToAction.class.getSimpleName();

    @SuppressWarnings("unchecked")
    @Override
    public Matcher<View> getConstraints() {
        return allOf(withEffectiveVisibility(Visibility.VISIBLE), isDescendantOfA(anyOf(
                isAssignableFrom(ScrollView.class),    isAssignableFrom(HorizontalScrollView.class), isAssignableFrom(NestedScrollView.class))));
    }

    @Override
    public void perform(UiController uiController, View view) {
        if (isDisplayingAtLeast(80).matches(view)) {
            Log.i(TAG, "View is already displayed. Returning.");
            return;
        }
        Rect rect = new Rect();
        view.getDrawingRect(rect);
        if (!view.requestRectangleOnScreen(rect, true /* immediate */)) {
            Log.w(TAG, "Scrolling to view was requested, but none of the parents      scrolled.");
        }
        uiController.loopMainThreadUntilIdle();
        if (!isDisplayingAtLeast(80).matches(view)) {
            throw new PerformException.Builder()
                    .withActionDescription(this.getDescription())
                    .withViewDescription(HumanReadables.describe(view))
                    .withCause(new RuntimeException(
                            "Scrolling to view was attempted, but the view is not displayed"))
                    .build();
        }
    }
    public static ViewAction betterScrollTo() {
        return ViewActions.actionWithAssertions(new ScrollToAction());
    }

    @Override
    public String getDescription() {
        return "scroll to";
    }}

The custom made ScrollToAction class is there because the normal scrollTo method is hardcoded to ScrollView and HorizontalScrollView, but not NestedScrollView.

This is the XML file that I am trying to test:

       <?xml version="1.0" encoding="utf-8"?>
       <android.support.v4.widget.NestedScrollView    xmlns:android="http://ift.tt/nIICcg"
        xmlns:app="http://ift.tt/GEGVYd"
        android:id="@+id/scrollView"
        xmlns:tools="http://ift.tt/LrGmb4"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">



            <FrameLayout
                android:id="@+id/fl"
                android:background="#FBFBFB"
                android:layout_margin="0dp"
                android:layout_width="match_parent"
                android:layout_height="350dp">

                <android.support.v4.view.ViewPager
                    android:id="@+id/container"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:layout_behavior="@string/appbar_scrolling_view_behavior" />

                <ImageView
                    android:id="@+id/location"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="@dimen/text_margin"
                    android:layout_gravity="left|top"
                    android:background="@null"
                    android:src="@drawable/ic_location_white"
                    android:paddingLeft="-8dp" />


                <TextView
                    android:id="@+id/textViewDistance"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_toRightOf="@id/location"
                    android:textAppearance="?android:attr/textAppearanceMedium"
                    android:layout_margin="@dimen/text_margin"
                    android:layout_gravity="left|top"
                    android:shadowColor="#262424"
                    android:shadowDx="1"
                    android:shadowDy="1"
                    android:shadowRadius="2"
                    android:textColor="#FBFBFB"
                    android:textSize="22dp"
                    android:singleLine="false"
                    android:paddingLeft="24dp" />


                <TextView
                    android:id="@+id/textViewPrice"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textAppearance="?android:attr/textAppearanceMedium"
                    android:layout_margin="@dimen/text_margin"
                    android:layout_gravity="right|top"
                    android:shadowColor="#262424"
                    android:shadowDx="1"
                    android:shadowDy="1"
                    android:shadowRadius="2"
                    android:textColor="#FBFBFB"

                    android:textSize="22dp"/>

                <me.relex.circleindicator.CircleIndicator
                    android:id="@+id/indicator"
                    android:layout_width="match_parent"
                    android:layout_height="40dp"
                    android:layout_gravity="bottom"
                    android:shadowColor="#262424"
                    android:shadowDx="1"
                    android:shadowDy="1"
                    android:shadowRadius="1"/>



            </FrameLayout>


            <LinearLayout

                android:layout_below="@id/fl"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                >

                <TextView
                    android:id="@+id/textViewTitle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:gravity="left"
                    android:layout_margin="@dimen/text_margin"
                    android:textColor="@color/colorCheckTomBlack"
                    android:textStyle="bold"
                    android:textSize="20dp" />

                <TextView
                    android:id="@+id/textViewDescription"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="@dimen/text_margin"
                    android:layout_marginRight="@dimen/text_margin"
                    android:gravity="left"
                    android:textColor="@color/colorCheckTomBlack"
                    android:textSize="18dp"
                    android:layout_weight="0.56" />

                <RelativeLayout
                    android:layout_width="match_parent"
                    android:layout_height="65dp"
                    android:paddingTop="30dp">


                    <ImageButton
                        android:id="@+id/buttonWatchlist"
                        android:src="@drawable/ic_checktom"
                        android:background="@null"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:gravity="left"
                        android:layout_marginLeft="55dp"
                        android:layout_marginStart="55dp"
                        android:layout_alignParentTop="true"
                        android:layout_alignParentLeft="true"
                        android:layout_alignParentStart="true"
                        android:onClick="launchWatchlistActivity"
                        android:paddingTop="2dp"/>


                    <ImageButton
                        android:id="@+id/buttonMessage"
                        android:src="@drawable/ic_messages"
                        android:background="@null"
                        android:scaleX="1.2"
                        android:scaleY="1.2"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center_horizontal"
                        android:layout_alignParentTop="true"
                        android:layout_centerHorizontal="true"
                        android:onClick="launchMessageActivity"
                        android:paddingTop="7dp"/>


                    <ImageButton
                        android:id="@+id/buttonShare"
                        android:src="@drawable/ic_share"
                        android:background="@null"
                        android:scaleX="1.5"
                        android:scaleY="1.5"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginRight="54dp"
                        android:layout_marginEnd="54dp"
                        android:layout_alignParentTop="true"
                        android:layout_alignParentRight="true"
                        android:layout_alignParentEnd="true"
                        android:onClick="launchShareActivity"/>



                </RelativeLayout>


                <RelativeLayout
                    android:orientation="horizontal"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:padding="2dp">


                    <TextView
                        android:id="@+id/textViewWatchlist"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Watchlist"
                        android:layout_marginLeft="41dp"
                        android:layout_marginStart="41dp"
                        android:layout_alignParentTop="true"
                        android:layout_alignParentLeft="true"
                        android:layout_alignParentStart="true" />


                    <TextView
                        android:id="@+id/textViewMessage"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Message"
                        android:layout_gravity="center_horizontal"
                        android:layout_alignParentTop="true"
                        android:layout_centerHorizontal="true" />

                    <TextView
                        android:id="@+id/textViewShare"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Share"
                        android:layout_gravity="center_horizontal"
                        android:layout_alignParentTop="true"
                        android:layout_alignParentRight="true"
                        android:layout_alignParentEnd="true"
                        android:layout_marginRight="52dp"
                        android:layout_marginEnd="52dp" />


                </RelativeLayout>
                <LinearLayout
                    android:orientation="horizontal"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center">


                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="_________________________________________"
                    android:paddingTop="25dp"/>


                </LinearLayout>

                <LinearLayout
                    android:orientation="horizontal"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center">

                    <de.hdodenhof.circleimageview.CircleImageView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_below="@+id/imageView"
                        android:layout_centerHorizontal="true"
                        android:id="@+id/circleView"
                        android:scaleX="0.4"
                        android:scaleY="0.4"
                        android:layout_marginTop="-20dp"
                        android:layout_marginBottom="-60dp"
                        />       

                </LinearLayout>

                <LinearLayout
                    android:orientation="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center">     
                    <LinearLayout
                        android:orientation="horizontal"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center">     
                    <TextView
                        android:id="@+id/textViewSellerName"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:textSize="18dp"/>     
                        </LinearLayout>        
                    <LinearLayout
                        android:orientation="horizontal"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="center">     
                    <TextView
                        android:id="@+id/textViewSellerDestination"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:paddingBottom="20dp" />     
                        <TextView
                            android:id="@+id/end_of_details"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content" />
                        </LinearLayout>        
                </LinearLayout>
            </LinearLayout>
        </RelativeLayout>
    </android.support.v4.widget.NestedScrollView>



When the test fails, this is the full output I get:

android.support.test.espresso.PerformException: Error performing 'scroll to' on view 'with id: com.checktom.checktom:id/end_of_details'. at android.support.test.espresso.PerformException$Builder.build(PerformException.java:83) at android.support.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:80) at android.support.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:56) at android.support.test.espresso.ViewInteraction.runSynchronouslyOnUiThread(ViewInteraction.java:184) at android.support.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:115) at android.support.test.espresso.ViewInteraction.perform(ViewInteraction.java:87) at com.checktom.checktom.ApplicationTest.testScrollDownAbilityOfDetailsScrollView(ApplicationTest.java:279) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at android.support.test.internal.statement.UiThreadStatement.evaluate(UiThreadStatement.java:55) at android.support.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:270) at org.junit.rules.RunRules.evaluate(RunRules.java:20) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runners.Suite.runChild(Suite.java:128) at org.junit.runners.Suite.runChild(Suite.java:27) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at org.junit.runner.JUnitCore.run(JUnitCore.java:115) at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59) at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1933) Caused by: java.lang.RuntimeException: Scrolling to view was attempted, but the view is not displayed at com.checktom.checktom.ScrollToAction.perform(ScrollToAction.java:52) at android.support.test.espresso.ViewInteraction$1.run(ViewInteraction.java:144) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:145) at android.app.ActivityThread.main(ActivityThread.java:6938) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199) Tests ran to completion.

I can tell that I run into the runtime exception in my ScrollToAction class's perform method, but I have yet to find a way to solve it.

In the first post I linked, the new BetterScrollTo method seemed to work like a charm.

If you need anything else from me, feel free to say so. I'll make sure to provide it asap.

Thanks in advance for any effort put into this.

Aucun commentaire:

Enregistrer un commentaire