24、模拟器与自动化测试:在模拟器上运行UI测试、Espresso测试配置、模拟器与Firebase Test Lab
自动化测试这件事,说实话,很多Android开发者在初期都会忽略。我自己刚入行那会儿也觉得「手动点一点不就行了?」直到有一次,我负责的一个电商App在发版前改了支付流程,结果忘了测试某个旧机型上的UI适配——上线后用户反馈支付按钮被键盘挡住了。嗯,从那以后,我再也不敢轻视UI自动化测试了。
这一章,我们就来聊聊怎么在模拟器上跑UI测试,怎么配Espresso,以及怎么把测试搬到Firebase Test Lab上去。
为什么要在模拟器上跑UI测试?
你可能会问:「真机测试不是更真实吗?」没错,真机确实更贴近用户环境。但模拟器有几个真机比不了的优势:
- 快速迭代:模拟器启动快,快照恢复秒级完成
- 多设备覆盖:一台电脑可以同时跑多个不同API级别的模拟器
- CI/CD集成:无头模式(headless)下跑测试,不依赖物理设备
- 成本低:不用买一堆真机
我个人习惯是:本地开发用模拟器跑快速验证,CI流水线里用Firebase Test Lab覆盖真机矩阵。
Espresso测试配置
Espresso是Google官方推荐的UI测试框架。它最大的特点是「同步」——它会自动等待UI线程空闲后再执行操作,所以你不用手动加Thread.sleep()。
添加依赖
在app/build.gradle里加上:
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation 'androidx.test:runner:1.5.2'
androidTestImplementation 'androidx.test:rules:1.5.0'
记得在defaultConfig里指定测试运行器:
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
一个简单的Espresso测试
假设我们有一个登录页面,包含用户名输入框、密码输入框和登录按钮。测试代码大概长这样:
@RunWith(AndroidJUnit4::class)
class LoginActivityTest {
@get:Rule
val activityRule = ActivityScenarioRule(LoginActivity::class.java)
@Test
fun testLoginSuccess() {
// 输入用户名
onView(withId(R.id.et_username))
.perform(typeText("admin"), closeSoftKeyboard())
// 输入密码
onView(withId(R.id.et_password))
.perform(typeText("123456"), closeSoftKeyboard())
// 点击登录
onView(withId(R.id.btn_login)).perform(click())
// 验证跳转到主页
onView(withId(R.id.tv_welcome))
.check(matches(withText("欢迎回来,admin")))
}
}
模拟器上运行UI测试
配置好之后,运行测试很简单。在Android Studio里,右键测试类或方法,选择「Run」。但有几个要点需要注意:
- 模拟器必须开启:如果模拟器没启动,AS会自动启动一个,但会慢一些
- API级别匹配:测试用的模拟器API级别最好和targetSdk一致
- 硬件加速:开启HAXM或Hypervisor.Framework,否则模拟器卡到怀疑人生
我个人建议在模拟器上先跑一遍完整的测试套件,确保所有用例通过,再提交代码。别问我为什么——有一次我偷懒没跑,结果CI上挂了8个测试,被同事笑了好久。
模拟器与Firebase Test Lab
Firebase Test Lab是Google提供的云端测试服务。你只需要上传APK和测试APK,它会在云端各种真机和模拟器上并行跑测试。好处很明显:
- 覆盖广:支持几十种设备,包括三星、华为、Pixel等主流机型
- 并行执行:多个设备同时跑,节省时间
- 结果详细:提供日志、截图、视频回放
配置Firebase Test Lab
首先,你需要在Firebase控制台创建一个项目,然后安装Firebase CLI:
npm install -g firebase-tools
firebase login
firebase init test-lab
接着,用gradle构建测试APK:
./gradlew assembleDebug assembleDebugAndroidTest
最后,上传到Test Lab:
gcloud firebase test android run \
--type instrumentation \
--app app/build/outputs/apk/debug/app-debug.apk \
--test app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk \
--device model=Pixel3,version=28 \
--device model=GalaxyS10,version=29 \
--timeout 30m
知识体系总览
下面这张图帮你理清模拟器测试的整体流程:
避坑指南
最后,分享几个我踩过的坑:
- 模拟器中文输入问题:有些模拟器默认没有中文输入法,测试中文文本输入时会失败。我建议在模拟器设置里添加Google拼音输入法。
- 动画导致测试超时:Espresso虽然会等待UI空闲,但窗口动画、转场动画有时会干扰。可以在测试设备上关闭动画:开发者选项 → 窗口动画缩放、过渡动画缩放、动画程序时长缩放 全部设为0。
- Firebase Test Lab网络限制:云端测试环境网络可能和本地不同,如果测试依赖特定网络状态(比如WiFi),记得在测试用例中模拟或跳过。
自动化测试这件事,前期配置确实有点繁琐,但一旦跑起来,你会发现它帮你省下的时间远超投入。尤其是团队协作时,每次提交都能自动验证UI是否正常,那种安心感,嗯,值得。