第3章:测试环境搭建(模拟器/真机/虚拟设备)

说句大实话,做Material 3组件测试,环境搭不好,后面全是白忙活。我之前带过一个项目,测试同学拿模拟器吭哧吭哧跑了三天,结果一上真机,全崩了——为啥?因为模拟器的渲染管线跟真机差太远。

所以这一章,我把这些年踩过的坑,还有总结出来的最佳实践,全盘托出。

3.1 三种环境,各自的门道

咱们做M3组件测试,主要面对三类环境:模拟器、真机、云端虚拟设备。各有利弊,没有万能的答案。

3.1.1 模拟器(Emulator)

Android官方的模拟器,其实已经做得相当不错了。尤其是Android 13、14这些版本,支持直接运行Compose预览。我个人习惯用Pixel 6 Pro的镜像,因为它基本覆盖了主流分辨率(1440x3120)。

场景推荐度原因
单组件视觉验证★★★★★速度快,截图稳定
手势交互测试★★★☆☆触摸模拟有偏差
动画过渡测试★★★★☆帧率可控,便于录制

要启动一个干净的模拟器实例,我一般这么搞:

# 创建稳定的Pixel 6 Pro模拟器
avdmanager create avd -n m3_test_pixel6 -k "system-images;android-34;google_apis;x86_64" -d pixel_6_pro

# 启动时关闭窗口动画,避免干扰
emulator -avd m3_test_pixel6 -no-window -no-audio -gpu swiftshader_indirect
别踩这个坑: 我曾经因为模拟器GPU驱动版本过低,导致Material 3的Motion效果出现伪影。一定要确保你的模拟器使用swiftshader_indirect或host模式,别用mesa。

3.1.2 真机(Physical Device)

真机测试才是检验真理的唯一标准。尤其是Material 3里那些细颗粒度的感官反馈——比如按下涟漪、滚动阻力、还有自适应布局的临界点——模拟器根本模拟不出那种感觉。

我建议你至少准备三台真机:

  • 主力机: Pixel 7/8(原生Android+最新Material You)
  • 兼容机: 三星Galaxy S23(One UI的Material 3适配)
  • 低配机: A系列或红米(测试性能瓶颈和布局截断)

连接真机后,跑个自动化用例,我会用这个脚本先做环境自检:

# 检查设备是否支持动态颜色
adb shell cmd uimode night yes
adb shell settings put secure theme_customization_overlay_packages "com.android.systemui:com.google.android.apps.nexuslauncher"

# 检查当前系统主题模式
adb shell dumpsys display | grep "mDefaultMode"
小技巧: 真机测试时,记得关闭系统的“自动亮度”和“深色模式自动切换”。否则你的测试Mock回放里,同一组件截图可能因为环境光变亮而产生色差——我中过招,连续跑了80组用例,最后发现20%的失败是因为亮度不一致。

3.1.3 云端虚拟设备(Cloud Virtual Device)

说白了就是Firebase Test Lab、AWS Device Farm这类服务。它们的好处是能覆盖你买不起的设备。但有个致命问题——延迟。

做Mock回放,尤其是需要逐帧比对渲染结果时,云端设备的截图回传会有几十毫秒到几百毫秒的抖动。所以我一般只用云端设备做回归筛查,不拿来做精细回放验证。

3.2 选择策略:到底用哪个?

你想想看,测试Material 3组件,什么场景最需要高保真?

我个人总结出一套“三层过滤”策略:

  1. 第一层(开发期): 模拟器 + Robolectric。测逻辑、测状态、测行为。速度快,秒级反馈。
  2. 第二层(提测前): 真机(主力机)+ 手工或半自动校验。测视觉、测手感、测无障碍焦点。
  3. 第三层(CI/CD): 云端设备 + 截图对比。测兼容性、测异常流程。
核心观点: Mock回放最怕环境不一致。同一个组件,在模拟器和真机上的字体渲染、阴影扩散、圆角抗锯齿都会不同。要保证回放可信度,必须锁定一个“回放基准环境”——我强烈建议用Pixel真机作为基准。

3.3 环境配置实战要点

下面这些配置项,是我在实际项目中反复调优过的。你直接抄作业就行。

3.3.1 字体与无障碍

Material 3的排版系统严重依赖字体缩放比例。如果测试设备开启了“大字体”,你的组件布局就会变形。

  • 关闭所有系统字体缩放
  • 设置最小宽度(dp)固定为360dp
  • 语言设置为英文(因为Material 3的排版参数基于拉丁字符优化)

3.3.2 颜色与主题

动态颜色(Monet)是Material 3最大的变量。同一个组件,在蓝色壁纸和粉色壁纸下,生成的主色完全不同。测试时一定要固定壁纸。

# 强制使用统一的静态主题(绕过Monet)
adb shell am broadcast -a android.intent.action.WALLPAPER_CHANGED \
  --es "wallpaper_component" "com.google.android.apps.nexuslauncher/.wallpaper.ColorCacheWallpaperService"
注意: 别直接在系统设置里改壁纸,那样会触发Monet实时重算,你后续所有截图都会变。我建议在测试App内通过dynamicColorTheme参数注入固定色板。

3.3.3 硬件加速与窗口

Material 3大量使用硬件层(View.LAYER_TYPE_HARDWARE)来提升动画性能。但模拟器可能不支持某些GPU特性,导致渲染结果与真机不同。

解决方法?我在项目的testInstrumentationRunner里加了这么个配置:

testInstrumentationRunnerArguments clearPackageData: 'true'
testInstrumentationRunnerArguments animationDisable: 'true'
testInstrumentationRunnerArguments gpuRendering: 'force_hardware'

3.4 核心知识结构

测试环境搭建决策流程 测试环境搭建核心决策流程 M3测试环境搭建 选择测试基准设备 模拟器 开发期快速验证 真机(Pixel) 回放基准环境 云端虚拟设备 兼容性回归筛查 配置项 GPU渲染 窗口动画关闭 配置项 固定壁纸与Monet 字体缩放关闭 配置项 截图回传延迟 仅做回归筛选用 输出:标准化Mock回放环境 注意:三层策略可并行 开发期→提测前→CI/CD

3.5 避坑与总结

最后,我得跟你掏心窝子说几句。做Mock回放,环境的一致性比测试用例本身还重要。我曾经因为模拟器时间没有冻结,导致每次截图里时钟位置的字不同,截图对比总是失败——后来整整排查了两天。

建议你这么做:
  • 把环境搭建步骤写成脚本,一键执行
  • 在每次回放前,做一次“环境完整性检查”
  • 把模拟器和真机的截图放在一起肉眼对比一轮,确保你看不出差别,再上自动化

环境折腾好了,接下来的章节咱们才能真正开始玩转Mock回放录制与比对。