移动应用测试自动化,35岁老码农的翻车与重生

Shell脚本侠
2026-02-03 08:17
阅读 295

上周五晚上十点半,我戴着耳机,单曲循环着 Radiohead 的《Karma Police》,手指在 MacBook 上敲出最后一行等待代码。窗外是上海徐汇区写字楼里永不熄灭的灯光,隔壁工位的实习生刚走,留下一罐没喝完的元气森林。而我,一个35岁还在写代码的老程序员,正被一个 UI 自动化测试脚本折磨得想把键盘扔进黄浦江。

事情是这样的:我们团队最近在做一款主打海外市场的电商 App,双11前要上线新功能,但 QA 同学天天在群里哀嚎:“手动测一轮要三天,版本又提测了,求求你们给点时间!”产品经理更是神补刀:“这个按钮点击后跳转不对,昨天不是修好了吗?怎么又坏了?”

那一刻,我突然意识到——再不搞自动化测试,我们这帮人怕是要在 2024 年底前集体猝死在工位上。

于是,我决定亲自下场,把移动应用测试自动化搞起来。毕竟,作为一个租房住公司附近、每天靠咖啡和代码续命的中年开发者,我早就受够了“线上回滚”、“紧急 hotfix”这些词儿。


为什么手动测试越来越扛不住?

先说说我们的现状。App 是 React Native 写的,iOS 和 Android 双端都有,每周至少两个版本提测。以前靠 QA 手动点点点,勉强能撑住。但随着业务复杂度飙升,页面跳转链路动辄七八层,加上各种网络状态、权限弹窗、设备适配……光是“登录-加购-结算”这一条路径,就得在十几种机型上跑一遍。

更惨的是,有一次因为某个组件在 Android 13 上渲染错位,导致用户无法点击“确认支付”,结果上线后半小时内退款率飙升。老板在周会上黑着脸问:“这种低级问题为什么没测出来?”QA 小哥委屈得快哭了:“我们只有一台 Pixel 7,其他都是模拟器啊……”

是的,现实就是这么骨感。手动测试不仅慢,还容易漏。尤其是在我们这种“敏捷开发、快速迭代”的节奏下,测试成了瓶颈中的瓶颈。


初探自动化:从 Appium 开始,但差点翻车

我一开始信心满满,觉得不就是写个脚本自动点按钮嘛,能有多难?于是翻出尘封已久的 Appium 教程,搭环境、写 capability、启动 driver,一顿操作猛如虎。

结果第一天就卡在“元素定位”上。React Native 的 View 在 iOS 上叫 XCUIElementTypeOther,在 Android 上又是 android.widget.FrameLayout,而且层级嵌套深得像俄罗斯套娃。更坑的是,有些按钮根本没有 accessibility ID,只能靠 XPath 硬怼,可一旦 UI 微调,XPath 就全崩。

# 这段 XPath 我写了整整两小时,第二天 UI 改了个 padding,直接失效
driver.find_element(By.XPATH, "//android.widget.FrameLayout[1]/android.widget.LinearLayout[2]/android.widget.Button[1]")

那几天我做梦都在背控件树。同事看我眼神都变了:“老张,你是不是压力太大了?要不要去 HR 那边聊聊?”

更要命的是,Appium 跑真机时经常卡死,日志里全是 Could not proxy command to remote server。我查了 Stack Overflow,有人说是因为 USB 调试不稳定,有人说要升级 WebDriverAgent,还有人建议直接换 Mac mini 搭 Jenkins —— 听起来都像在劝我转行。


转机:Claude Code v0 带来的“偷懒”新思路

就在我不知所措时,偶然在 GitHub Trending 上看到一个叫 Claude Code v0 的项目(注意:这不是 Anthropic 的 Claude,而是社区开源的一个轻量级测试辅助工具,名字蹭了热度,但确实好用)。

它干了件特别聪明的事:不直接操作 UI,而是通过埋点 + 逻辑校验来间接验证行为

比如,我们原本要测试“点击购物车图标后跳转到购物车页”,传统做法是找图标元素、点击、等新页面加载、再找“购物车”标题。但 Claude Code v0 的思路是:

  1. 在点击事件触发时,前端主动上报一个 event: cart_clicked
  2. 测试脚本监听这个事件
  3. 同时检查当前路由是否变为 /cart
  4. 如果两者匹配,就认为测试通过

这样就绕开了脆弱的 UI 定位问题,稳定性直线上升。

我试着在项目里加了几行埋点:

// React Native 组件中
const handleCartPress = () => {
  analytics.logEvent('cart_clicked'); // 上报事件
  navigation.navigate('Cart');
};

然后在测试脚本里:

from claude_code_v0 import TestClient

client = TestClient(app_id="com.example.shop")
client.start_monitoring()

cart_button.click()
assert client.wait_for_event("cart_clicked", timeout=5)
assert current_route() == "/cart"

跑起来居然一次成功!那天晚上我激动得喝了三杯美式,差点心悸。


真实落地:从“玩具”到“生产线”的跨越

当然,理想很丰满,现实还得搬砖。要把这套东西用在生产环境,得解决几个硬骨头:

1. 多平台适配怎么办?

Claude Code v0 本身是跨平台的,但它依赖的埋点方案得统一。我们最后决定:

  • iOS 用 Firebase Analytics
  • Android 用自研的轻量 SDK(为了合规)
  • Web 用 GA4

但事件命名必须一致,比如都叫 cart_clicked。为此我们建了个内部 Wiki,强制所有 FE/移动端同学按规范打点。

2. 性能会不会拖慢 App?

这是老板最关心的问题。我们做了 A/B 测试:

方案 冷启动耗时 (ms) 内存占用增量 包体积增加
无埋点 1200 0 MB 0 KB
全量埋点 1280 +3 MB +180 KB
Claude Code v0(仅测试环境) 1210 +0.5 MB +40 KB

结论:只要在 release 构建时关掉测试埋点,几乎无影响。我们用 __DEV__ 和构建 flag 控制:

if (__DEV__ && process.env.TEST_MODE) {
  analytics.logEvent(...);
}

3. 如何集成到 CI/CD?

我们用的是 GitLab CI,每提交 PR 就自动跑核心路径的自动化测试。配置如下:

test_mobile_e2e:
  stage: test
  script:
    - npm run build:android:test
    - python scripts/run_claude_tests.py --platform android
    - python scripts/run_claude_tests.py --platform ios
  artifacts:
    paths:
      - test-reports/
  only:
    - merge_requests

现在,只要 PR 里改了购物流程,CI 就会自动跑 10 条核心路径。如果失败,直接 block 合并。产品经理再也不敢说“这个小改动应该没问题”了。


成果:从“救火”到“预防”

上线三个月后,数据说话:

  • 核心路径回归测试时间从 3 天 → 45 分钟
  • 线上 P0 级 Bug 下降 68%
  • QA 同学终于有时间做探索性测试,而不是重复点点点
  • 我自己……嗯,至少不用再半夜被 PagerDuty 叫醒

最让我感动的是,上周 QA 主管请我喝奶茶,说:“老张,你这玩意儿救了我们全家。”(夸张了,但意思到了)


给新手的几点真心话

如果你也正被移动测试折磨,别慌,分享几个血泪经验:

  1. 别一上来就追求 100% 覆盖。先搞定最核心的 3-5 条路径(比如登录、下单、支付),这些路径出问题代价最高。
  2. UI 自动化是最后手段。能用接口测就用接口,能用逻辑校验就别碰 UI。Claude Code v0 的思路值得借鉴。
  3. 真机 > 模拟器。尤其涉及权限、通知、后台唤醒等场景,模拟器根本测不准。我们后来买了个二手 iPad 和 Pixel 6 当“测试专用机”。
  4. 让开发参与埋点。测试不是 QA 一个人的事。我们团队现在要求 PR 必须包含对应测试用例,否则不 merge。
  5. 别信“一键生成脚本”。市面上有些工具号称能录制操作自动生成代码,但维护成本极高,UI 一变全废。

最后:35岁还在写代码,图个啥?

有人问我,都这年纪了,干嘛还折腾新技术?不如混混日子等退休。

但我觉得,写代码最爽的不是炫技,而是解决问题。当看到自己写的测试脚本在凌晨三点自动跑完,发现了一个潜在的支付漏洞,那种“我保护了用户的钱包”的感觉,比涨工资还爽。

而且,学 Claude Code v0 的过程,也让我重新找回了刚入行时的热情。原来,35岁不是终点,而是换个姿势继续跑。

对了,最近我在用业余时间学 LLM + 自动化测试结合,比如用 AI 生成测试用例。虽然还不成熟,但想想就兴奋——或许下次写文章,就是《用大模型给 App 做“体检”》了。

耳机里,Radiohead 唱到:“This is what you get when you mess with us…

我笑了笑,保存代码,按下运行键。

夜还长,bug 还多,但至少,我们不再裸奔。

评论 0

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