You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级Android Material版本致Firebase测试失败,但本地测试正常

Material组件升级1.6.0-alpha01后FTL Espresso测试失败问题分析与解决

核心问题

将com.google.android.material:material从1.5.0升级到1.6.0-alpha01后,针对包含MaterialAutoCompleteTextView的TextInputLayout的FTL测试出现NoMatchingRootException,表现为下拉菜单未弹出,但本地测试及旧版本FTL环境可正常通过。

可能原因

  1. 下拉菜单根视图类型变更:1.6.0-alpha01重构了ExposedDropdownMenu的实现,原有的PopupWindow$PopupViewContainer根视图被替换为其他类型,导致isPlatformPopup()匹配失败。
  2. FTL环境动画延迟:FTL测试环境的动画渲染速度慢于本地,新版本组件的下拉动画未完成时,Espresso就开始查找子项。
  3. 点击触发逻辑变更:新版本中点击TextInputLayout触发下拉的逻辑被调整,需要直接点击MaterialAutoCompleteTextView才能弹出菜单。

解决方案

1. 调整根视图匹配器

自定义匹配器适配新版本的下拉菜单根视图,替代isPlatformPopup():

public static Matcher<Root> isMaterialDropdownRoot() {
    return new TypeSafeMatcher<Root>() {
        @Override
        public void describeTo(Description description) {
            description.appendText("匹配Material下拉菜单根视图");
        }

        @Override
        protected boolean matchesSafely(Root root) {
            String decorViewClassName = root.getDecorView().getClass().getName();
            // 匹配Material组件下拉菜单的容器类
            return decorViewClassName.contains("PopupViewContainer") 
                    && !root.isDialog()
                    && root.hasWindowFocus();
        }
    };
}

修改测试代码:

onView(withId(R.id.textInputLayout)).perform(scrollTo(), click())
onView(withText("Dropdown Name"))
    .inRoot(isMaterialDropdownRoot())
    .perform(click())

2. 添加显式等待逻辑

针对FTL环境的延迟问题,添加等待视图出现的逻辑:

public static ViewAction waitForView(final Matcher<View> matcher, long timeoutMs) {
    return new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return isAssignableFrom(View.class);
        }

        @Override
        public String getDescription() {
            return "等待视图出现,超时时间:" + timeoutMs + "ms";
        }

        @Override
        public void perform(UiController uiController, View view) {
            uiController.loopMainThreadUntilIdle();
            long endTime = System.currentTimeMillis() + timeoutMs;
            do {
                for (View child : TreeIterables.breadthFirstViewTraversal(view)) {
                    if (matcher.matches(child)) return;
                }
                uiController.loopMainThreadForAtLeast(50);
            } while (System.currentTimeMillis() < endTime);
            throw new PerformException.Builder()
                    .withActionDescription(getDescription())
                    .withCause(new TimeoutException("视图未在超时时间内出现"))
                    .build();
        }
    };
}

测试代码中添加等待:

onView(withId(R.id.textInputLayout)).perform(scrollTo(), click())
// 等待下拉菜单项出现
onView(isRoot()).perform(waitForView(withText("Dropdown Name"), 3000))
onView(withText("Dropdown Name"))
    .inRoot(isPlatformPopup())
    .perform(click())

3. 直接点击MaterialAutoCompleteTextView

修改测试逻辑,直接点击输入框而非父布局:

onView(withId(R.id.autoCompleteTextView)).perform(scrollTo(), click())
onView(withText("Dropdown Name"))
    .inRoot(isPlatformPopup())
    .perform(click())

4. 禁用测试环境动画

在build.gradle中全局禁用动画:

android {
    testOptions {
        animationsDisabled = true
    }
}

或在测试类中通过命令行禁用系统动画:

@Before
public void setup() {
    UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
    try {
        device.executeShellCommand("settings put global window_animation_scale 0");
        device.executeShellCommand("settings put global transition_animation_scale 0");
        device.executeShellCommand("settings put global animator_duration_scale 0");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

内容的提问来源于stack exchange,提问作者cchman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 22:35:08