当包含浮动操作按钮的视图显示 Snackbar 时,Android espresso 测试会冻结。

5
我假设这是一个bug,但我可能做错了什么。
我的布局非常简单,只包含一个浮动操作按钮:
<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"/>

我的活动只继承了包含以下内容的onCreate方法:
 @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();

}

我编写了一个 Espresso 测试,仅验证 Snackbar 在半秒钟内是否显示。

@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()));
}

当我调试此测试时,onView(withText(R.string.snackbar_message)).check(matches(isDisplayed())); 在 Snackbar 消失执行。
到目前为止,我已经找到了三种解决此问题的方法,当:
  • 将 FloatingActionButton 的 anchorGravity 更改为 top:app:layout_anchorGravity="top|right|end"

  • 完全删除 FloatingActionButton

  • 将 Snackbar 的第一个参数更改为使用 findViewById(android.R.id.content)。但是,当 snackbar 出现时,它不会将 FloatingActionButton 推上去。

正如我所说,我认为这是一个错误,请让我知道我是否做错了什么。

使用 sleep() 方法是一个错误。你应该使用一些循环测试线程的 ViewAction。另外,Espresso 与动画不兼容。在设备开发者选项中关闭动画,然后尝试启动测试。 - Karol Kulbaka
@KarolKulbaka 动画已关闭,没有休眠,测试也会挂起。 - Sammekl
你尝试过使用 ActivityMonitor 吗?(https://developer.android.com/reference/android/app/Instrumentation.ActivityMonitor.html)比如,等待活动出现后再检查你的 Snackbar。 - Anton Malmygin
Anton Malmygin,我已经尝试过了,但正如我在问题中所说的那样,问题似乎是直到 snackbar 消失之前,我的所有测试代码都没有被执行。 - Sammekl
1个回答

10

您在xml中构建布局的方式似乎会导致UI与Snackbar交互时不断更新。

您找到的三种解决方案有一个共同点,它们都消除了Snackbar和FAB按钮之间的交互。当您将重力设置为TOP时,Snackbar不会推动按钮,因为它们位于屏幕的不同端口。当您完全删除FAB按钮时,也没有任何交互。当您更改传递给Snackbar builder的视图时,也没有交互,因为Snackbar显示在按钮上方。

如果您在“设置”>“开发人员选项”中启用“显示表面更新”,您实际上会看到在展示Snackbar时UI正在更新。Espresso轮询UI线程以查找何时处于空闲状态。由于Snackbar使UI线程忙碌,因此Espresso在Snackbar消失之前不会运行测试代码。

这似乎与以下内容有关:

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

如果你用以下内容替换它们:
android:layout_gravity="bottom|end"

排版结果看起来相同,测试运行正确。如果启用了Show Surface Updates选项,则可以看到在显示Snackbar时UI未更新。


我简直不敢相信我自己没有想到这个..即使是Android浮动操作按钮的文档也展示了锚点的示例。非常感谢您的帮助,这解决了问题! - Sammekl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接