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")))
    }
}
小技巧: 用closeSoftKeyboard()关闭键盘,避免键盘遮挡导致后续操作失败。我曾经踩过这个坑,测试一直报错,查了半天才发现是键盘没关。

模拟器上运行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
注意: Firebase Test Lab是收费服务,但每月有免费额度。个人项目和小团队基本够用。如果测试量很大,记得设置预算上限,避免意外扣费。

知识体系总览

下面这张图帮你理清模拟器测试的整体流程:

模拟器与自动化测试知识体系 测试准备 添加Espresso依赖 编写测试用例 onView + perform + check 本地运行 模拟器/真机 选择测试环境 Firebase Test Lab 云端多设备并行测试 本地模拟器 快速调试与验证 测试报告与截图

避坑指南

最后,分享几个我踩过的坑:

  • 模拟器中文输入问题:有些模拟器默认没有中文输入法,测试中文文本输入时会失败。我建议在模拟器设置里添加Google拼音输入法。
  • 动画导致测试超时:Espresso虽然会等待UI空闲,但窗口动画、转场动画有时会干扰。可以在测试设备上关闭动画:开发者选项 → 窗口动画缩放、过渡动画缩放、动画程序时长缩放 全部设为0。
  • Firebase Test Lab网络限制:云端测试环境网络可能和本地不同,如果测试依赖特定网络状态(比如WiFi),记得在测试用例中模拟或跳过。

自动化测试这件事,前期配置确实有点繁琐,但一旦跑起来,你会发现它帮你省下的时间远超投入。尤其是团队协作时,每次提交都能自动验证UI是否正常,那种安心感,嗯,值得。

公众号:蓝海资料掘金营,微信 deep3321