Android espresso test freezes when snackbar is showing only when view contains Floating Action Button
Asked Answered
E

1

5

I assume that this is a bug, but I might be doing something wrong.

My layout is very simple and only contains a floating action button:

<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/contentCoordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
    android:id="@+id/layoutWithoutContent"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

</LinearLayout>

<android.support.design.widget.FloatingActionButton
    android:id="@+id/stopButton"
    android:src="@drawable/ic_stop_white_24px"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginRight="16dp"
    android:layout_marginBottom="16dp"
    app:layout_anchor="@id/layoutWithoutContent"
    app:backgroundTint="@color/colorPrimary"
    app:layout_anchorGravity="bottom|right|end"/>

My activity only inherits the onCreate method containing:

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    CoordinatorLayout coordinatorLayout = findViewById(R.id.contentCoordinatorLayout);
    Snackbar.make(coordinatorLayout, R.string.snackbar_message, Snackbar.LENGTH_LONG).show();

}

I wrote an Espresso test which only validates that the Snackbar is shown within halve a second

@Rule
public ActivityTestRule<MainActivity> mainActivity = new ActivityTestRule<>(MainActivity.class, true, true);

@Test
public void testSnackbarIsShown() throws Exception {        onView(withText(R.string.snackbar_message)).check(matches(isDisplayed()));
}

When I debug this test, onView(withText(R.string.snackbar_message)).check(matches(isDisplayed())); is executed after the snackbar disappeared.

So far I have found 3 ways to resolve this issue, the issue is resolved when:

  • I change the FloatingActionButton's anchorGravity to top: app:layout_anchorGravity="top|right|end"

  • I remove the FloatingActionButton completely

  • Change the first argument of the Snackbar to use findViewById(android.R.id.content). But this does not push the FloatingActionButton up when the snackbar appears.

As I said, I assume this is a bug, but please let me know if I'm doing something wrong here.

Ezzo answered 7/11, 2017 at 8:20 Comment(4)
Using sleep() method is a mistake. You should use some ViewAction which loops test tread. Other thing is that espresso don't work well with animations. Turn of animations on device developer options and then try to launch test.Foldaway
@KarolKulbaka Animations are off and without the sleep, the test hangs as well.Ezzo
Did you tried with ActivityMonitor ? (developer.android.com/reference/android/app/…) Like, wait for activity to appear and only after check your snackbar.Profligate
Anton Malmygin, I have tried it but as I said in my question, the problem seems to be that none of my test code is executed until the snackbar has disappeared.Ezzo
S
10

There's something about the way you built your layout in the xml that makes the UI update constantly when the Snackbar interacts with the FAB button.

The three solutions that you found have one thing in common, they remove the interaction between the Snackbar and the FAB button. When you set the gravity to TOP, the Snackbar does not push the button because they are in different ends of the screen. When you remove the FAB button completely there is no interaction either. And when you change the view you pass to the Snackbar builder, there's also no interaction since the Snackbar shows on top of the button.

If you enable Show Surface Updates in Settings > Developer options, you will actually see that the UI is being updated while the Snakcbar is shown. Espresso polls the UI thread trying to find when it's idle. Since the Snackbar is keeping the UI thread busy, Espresso does not run the test code until the Snackbar disappears.

It seems to be related to:

app:layout_anchor="@id/layoutWithoutContent"
app:layout_anchorGravity="bottom|right|end"

If you replace them with:

android:layout_gravity="bottom|end"

The resulting layout looks the same and the test runs correctly. If you have Show Surface Updates enabled you'll see that the UI is not updated while the Snackbar is shown.

Subantarctic answered 18/11, 2017 at 15:31 Comment(1)
I can't believe I did not figure this out myself.. Even the Android documentation for floating action buttons show examples with the anchors. Thanks a lot for your help, this fixed the issue!Ezzo

© 2022 - 2024 — McMap. All rights reserved.