升级Travis测试的Android API至24后,Espresso测试持续报错求助
先把你遇到的错误贴出来,方便其他开发者参考:
com.simplemobiletools.calculator.MainActivityTest > divisionByZeroTest[test(AVD) - 7.0] FAILED
java.lang.RuntimeException: Waited for the root of the view hierarchy to have window focus and not request layout for 10 seconds. If you specified a non default root matcher, it may be picking a root that never...
我之前把项目从API 22升级到24时,也碰到过一模一样的问题。主要是API 24开始Espresso对视图布局和焦点的检测逻辑更严格,再加上Android 7.0(API24)的系统行为变化,才导致了这个超时错误。给你几个亲测有效的解决方向:
1. 强制关闭系统动画
API 24之后,系统动画会严重干扰Espresso的视图状态检测——尤其是在Travis这类CI环境里,模拟器性能本来就有限,动画会让布局一直处于"请求重绘"的状态。你可以在Travis的测试脚本里添加这几条命令,在启动AVD后执行:
adb shell settings put global window_animation_scale 0 adb shell settings put global transition_animation_scale 0 adb shell settings put global animator_duration_scale 0
这会彻底关闭系统所有动画,让Espresso能准确检测到视图是否稳定。
2. 添加布局等待的IdlingResource
如果你的应用里有异步加载、自定义View或者复杂布局,API 24下Espresso可能没等到布局完全稳定就开始执行测试了。你可以自定义一个LayoutIdlingResource来监听视图树的布局请求,直到没有布局请求为止:
public class LayoutIdlingResource implements IdlingResource { private final View mRootView; private ResourceCallback mCallback; public LayoutIdlingResource(View rootView) { mRootView = rootView; mRootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (mCallback != null) { mCallback.onTransitionToIdle(); } // 移除监听避免重复回调 mRootView.getViewTreeObserver().removeOnGlobalLayoutListener(this); } }); } @Override public String getName() { return LayoutIdlingResource.class.getName(); } @Override public boolean isIdleNow() { return !mRootView.isLayoutRequested(); } @Override public void registerIdleTransitionCallback(ResourceCallback callback) { mCallback = callback; } }
然后在测试中注册这个IdlingResource:
@Rule public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class); @Before public void setUp() { View rootView = mActivityRule.getActivity().findViewById(android.R.id.content); IdlingRegistry.getInstance().register(new LayoutIdlingResource(rootView)); } @After public void tearDown() { IdlingRegistry.getInstance().unregisterAll(); }
3. 调整Travis的AVD配置
API 24的模拟器在Travis默认配置下可能性能不足,导致布局加载超时。你可以在.travis.yml里给模拟器分配更多内存,并且使用x86镜像(比ARM镜像快很多):
android: components: - tools - platform-tools - build-tools-30.0.2 - android-24 - sys-img-x86-android-24 emulator: - emulator -avd test -no-window -no-audio -memory 2048 -accel on
另外,记得在启动模拟器后添加sleep 60之类的等待命令,让AVD完全启动后再开始测试。
4. 检查布局文件和自定义View的兼容性
API 22到24之间,一些布局属性的行为发生了变化,比如android:fitsSystemWindows在API 24后的处理逻辑不同,或者自定义View的onMeasure方法在新API下触发了无限重绘。你可以在本地用API 24的模拟器运行测试,打开开发者选项里的"显示布局边界"和"显示GPU过度绘制",检查是否有视图一直在重复布局。
我当时是靠关闭动画+调整AVD内存解决的问题,希望这些方法对你有用!
内容的提问来源于stack exchange,提问作者K. Vu

