手写代码老炮儿的移动测试自动化实战

需求之外
2026-05-17 20:00
阅读 1181

上周五晚上十一点,办公室只剩我和隔壁组一个运维兄弟。他盯着屏幕上的报警邮件发愣,我则在 Vim 里反复调试一段 Appium 脚本——这已经是我连续第三天加班了。起因很简单:产品经理在周一晨会上拍桌子说:“双11前必须实现核心链路全自动化回归,不然谁也别想休假。”

我是那种典型的“手写代码但也在尝试AI辅助”的保守派。平时写业务逻辑喜欢用 Vim + tmux 组合拳,对 IDE 自动补全嗤之以鼻;但最近也被团队逼着试了几次 GitHub Copilot,偶尔真能省下几行样板代码。坐标成都,生活节奏舒服,但项目 deadline 一来,照样得通宵。尤其搞移动开发,Android 和 iOS 两个平台来回切,光是设备适配就能让人头秃。

这次要解决的问题很实际:我们团队维护一款电商类 App,用户量不小,但测试全靠人工点点点。每次发版前 QA 同学都得手动跑五十多个核心场景,耗时不说,还总漏测。上个月就因为一个购物车清空逻辑没覆盖到,导致线上订单异常,被老板在周报里点名批评。于是,自动化测试这事,终于从“可做可不做”变成了“不做就滚”。

别被花哨工具忽悠,先理清需求

一开始我以为这事简单:不就是写几个脚本自动点击按钮嘛?结果第一天就翻车了。我随手搭了个基于 Appium 的框架,结果在 iOS 真机上跑不通——Xcode 升级后 WebDriverAgent 编译失败,错误信息看得我血压飙升:

xcodebuild: error: Unable to find a destination matching the provided destination specifier

折腾半天才发现是新系统限制了设备权限。那一刻我真的想砸电脑。后来冷静下来一想:移动测试自动化不是炫技,关键是稳定、可维护、能跑在 CI 上。于是重新梳理需求:

  • 支持 Android 和 iOS 双端
  • 能在 Jenkins 上定时执行
  • 失败用例自动截图+录屏
  • 测试报告要清晰,最好能对接 Jira

明确了目标,才不至于在工具选型上走弯道。Appium 虽然老,但社区成熟、跨平台支持好,依然是首选。至于 Llama?别误会,这里不是 Meta 那个大模型——是我们内部给自动化测试框架起的代号,取自“Llama is Light and Modular for Mobile Automation”,纯粹图个顺口,顺便蹭点 AI 热度让领导觉得我们“前沿”。

从零搭建 Llama:踩坑比写代码多

Llama 的核心架构其实不复杂:Python + Appium + pytest + Allure。但魔鬼都在细节里。

设备管理是个坑

最头疼的是真机管理。iOS 必须用真机(模拟器很多权限拿不到),Android 虽然可以用模拟器,但性能差异大,最终还是上了真机池。我们搞了六台旧手机挂在 USB Hub 上,用 adb devicesios-deploy 管理。但经常出现设备离线、证书过期、USB 掉线等问题。后来写了个守护脚本,每五分钟检查一次设备状态,自动重启 adb 和重装测试包。

#!/bin/bash
# device_health_check.sh
adb kill-server && adb start-server
for dev in $(adb devices | grep -v "List" | awk '{print $1}'); do
    if ! adb -s $dev shell getprop ro.product.model > /dev/null 2>&1; then
        echo "Device $dev offline, restarting..."
        # 触发硬件重连逻辑(略)
    fi
done

元素定位:别信 UIAutomatorViewer

早期我迷信 Android Studio 自带的 UIAutomatorViewer,结果发现它抓出来的 resourceId 在不同 ROM 上完全不一样。华为改包名、小米加前缀、OPPO 直接给你随机 ID……最后统一改用 XPath + accessibilityId 混合策略,并强制要求前端同学在关键控件上加上 testIDcontent-desc。为此我还专门拉了个跨团队规范文档,被前端同事吐槽:“你们测试是不是闲的?”

iOS 倒是相对规范,但 SwiftUI 出现后,很多动态生成的 View 没有明确标识。这时候就得靠 labelvalue 组合判断,或者干脆用图像识别——但这又引入了新的不稳定因素。

网络隔离与 Mock

自动化测试最怕依赖外部服务。有一次因为支付回调超时,整个回归套件卡住两小时。后来我们在测试环境做了全链路 Mock:用 MitmProxy 拦截请求,返回预设的 JSON。关键接口如登录、下单、库存查询全部 mock 掉,只保留 UI 交互的真实性。

# mock_server.py 片段
def mock_login(request):
    return {
        "code": 200,
        "data": {"user_id": "test_123", "token": "fake_jwt_token"}
    }

这套机制上线后,单次回归时间从 45 分钟压到 12 分钟,稳定性也大幅提升。

效果如何?数据说话

Llama 框架跑了一个月后,我们统计了关键指标:

指标 自动化前 自动化后(Llama)
单次回归耗时 45 min 12 min
人力投入 2人天/周 0.5人天/周(维护)
漏测率 ~8% <1%
发版阻塞次数(月) 3-4次 0次

最爽的是双11前一周,我们每天凌晨 2 点自动跑全量回归,早上来就能看到 Allure 报告。有一次凌晨三点报警,显示“优惠券领取失败”,点开录屏一看,原来是前端不小心把按钮 disabled 了——这种低级错误以前总要等到 QA 白天测试才发现,现在直接拦截在提测前。

开发心得:自动化不是银弹,但值得投入

搞完这一轮,我对移动测试自动化有了几点朴素认知:

  1. 别追求 100% 覆盖:UI 自动化天生脆弱,重点覆盖核心路径(登录、下单、支付)即可,边缘场景还是靠单元测试和人工。
  2. 维护成本比编写成本高:脚本写三天,维护三个月。所以代码结构一定要清晰,注释不能少,我甚至给每个用例写了“预期行为说明”。
  3. 和前端搞好关系:没有可测性的 UI 就是灾难。推动他们加 testID,比你自己写一百个 xpath 都管用。
  4. AI 辅助可以试试,但别依赖:我让 Copilot 帮我生成过一些基础操作函数,比如“滑动到元素可见”,它确实能写出可用代码。但涉及业务逻辑判断时,它经常胡说八道。手写代码的老习惯,暂时还丢不掉。

最后说句实在话:自动化测试不会让你升职加薪,但它能让你在双11这种大促期间睡个好觉。作为一个生活在成都、喜欢慢节奏的程序员,能按时下班陪家人吃火锅,比什么都强。

现在 Llama 已经成了我们团队的标准基建。虽然它名字听着高大上,其实内核很朴素:稳定、实用、不折腾。就像我的 Vim 配置——没有 fancy 插件,但敲起代码来,心里踏实。

下次要是产品经理再说“加个新功能很简单”,我就把 Llama 的维护日志甩他脸上。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝