移动应用测试自动化实践:一个在家炼丹的AI工程师的踩坑日记

高效_创造者
2025-12-16 11:29
阅读 522

大家好,我是小李,一个远程办公、天天和模型参数死磕的AI算法工程师。最近一年,除了调参炼丹,我还被临时抓壮丁去搞了一个移动App的自动化测试项目。别问,问就是“算法组也要懂全栈”——这是我们CTO在全员会上说的,当时我正在用GPU跑ResNet,差点没把咖啡喷到屏幕上。

事情是这样的:我们团队去年接了个新业务,要做一个面向C端用户的AI图像处理App(对,就是那种一键美颜+智能抠图+老照片修复三合一的玩意儿)。产品上线节奏卡得特别死——双11前必须上架。但问题是,我们的QA团队只有两个人,而App要同时支持iOS和Android,还要适配十几种主流机型。手动测试?等测完黄花菜都凉了。

更扎心的是,我那会儿正好在更新简历准备跳槽(别装了,谁没偷偷改过简历),看到某大厂JD里赫然写着:“有移动端自动化测试经验者优先”。行吧,为了简历能多一行亮点,也为了不被产品经理半夜钉钉轰炸,我咬牙接下了这个“副业”。


从0到1:为什么我们非得搞自动化?

先说背景。我们的App前端用React Native写的(别骂,历史原因),后端是标准的微服务架构,跑在K8s集群上——这部分我很熟,但移动端?说实话,我上次写Android代码还是大学课程设计,用的还是Eclipse。

一开始我以为自动化测试就是写几个脚本点点按钮,结果现实狠狠打了我的脸。比如:

  • iOS上滑动列表正常,Android某些低端机直接卡死
  • 华为手机的返回键触发逻辑和其他厂商不一样
  • 某些机型拍照权限弹窗样式不同,导致元素定位失败

最离谱的一次:测试脚本在本地Mac上跑得好好的,一放到CI/CD流水线就挂。排查半天发现是Docker容器里没装Android模拟器的图形驱动……运维兄弟看了直摇头:“你这需求比训练LLM还难伺候。”

所以,自动化不是可选项,是活命符。尤其是当我们发现每次发版前QA要手动回归200+用例,耗时3天,而产品那边天天催:“能不能今天上线?竞品已经上了!”——那一刻我悟了:再不自动化,我就要变成人肉测试机了。


技术选型:Appium真香,但坑也不少

经过一番调研(其实就是Google+Stack Overflow+翻公司旧项目),我们最终选了 Appium + WebDriverIO + Jest 这套组合拳。理由很简单:跨平台、社区活跃、和我们现有的Web自动化框架能复用部分逻辑。

Appium 是个开源的移动端自动化测试框架,支持iOS和Android,用WebDriver协议通信。简单说,它让你用写Web测试的方式写App测试。

但真上手才发现,Appium的“Write once, run anywhere”口号听听就好。实际开发中,光是元素定位就能让你怀疑人生。

比如登录页的“手机号输入框”,在iOS上是 XCUIElementTypeTextField,在Android上可能是 android.widget.EditText,更别说有些厂商魔改了View层级。最后我们不得不搞了一套平台适配层

// helpers/locator.js
const LOCATORS = {
  login: {
    ios: {
      phoneInput: '//XCUIElementTypeTextField[@name="phone"]',
      submitBtn: '//XCUIElementTypeButton[@name="login"]'
    },
    android: {
      phoneInput: '//android.widget.EditText[@resource-id="com.myapp:id/phone"]',
      submitBtn: '//android.widget.Button[@text="登录"]'
    }
  }
};

export const getLocator = (page, element, platform) => {
  return LOCATORS[page][platform][element];
};

虽然啰嗦,但至少保证了测试脚本的可维护性。后来我还把这个模块抽出来,写进了我的简历项目经历里:“设计跨平台元素定位策略,提升脚本复用率60%”——HR看了都说专业。


真实战场:那些让我想砸电脑的瞬间

坑1:异步加载 & 动画干扰

App里到处都是Loading、转场动画、懒加载列表。如果直接 click(),经常点到空气上。一开始我暴力加 sleep(5000),结果被同事嘲讽:“你这是测试还是冥想?”

后来改用 显式等待(Explicit Wait)

await driver.waitUntil(
  async () => {
    const elem = await driver.$(selector);
    return await elem.isDisplayed();
  },
  { timeout: 10000, timeoutMsg: 'Element not displayed' }
);

配合 Appium 的 automationName 参数(iOS用XCUITest,Android用UiAutomator2),稳定性终于上来了。

坑2:真机 vs 模拟器

模拟器跑得快,但和真机行为差异巨大。比如:

  • 模拟器网络请求秒回,真机可能超时
  • 模拟器没摄像头,没法测拍照功能
  • 某些机型(looking at you, 小米)后台限制太狠,App切后台就杀进程

我们最终采用 混合策略

测试类型 执行环境 频率
冒烟测试 云真机(AWS Device Farm) 每次PR
回归测试 本地模拟器 每日构建
兼容性测试 内部真机池 发版前

顺便吐槽一句:租云真机真的很贵!但比起线上事故背锅,这钱花得值。

坑3:测试数据污染

App测试最大的痛点:状态难以重置。你测完登录,下次测试还得先退出。我们试过清App数据、重装APK,但速度慢到哭。

灵光一闪,我想到:既然后端是微服务,能不能让测试用例自带上下文?比如每个测试账号绑定一个独立的用户ID,测试结束自动清理。于是我们搞了个 Test User Manager 服务,通过API动态创建/销毁测试账号。这招不仅解决了数据污染,还让并行测试成为可能——现在CI里能同时跑20个设备,爽歪歪。


融入CI/CD:让自动化真正“自动”起来

作为K8s老用户,我坚决反对“本地跑通就算成功”。真正的自动化必须融入流水线。我们在GitLab CI里加了这么一段:

mobile_test:
  stage: test
  image: appium/appium-docker-android
  services:
    - name: selenium/standalone-chrome
      alias: selenium
  script:
    - npm install
    - npm run test:android -- --spec specs/smoke.spec.js
  only:
    - merge_requests

关键点:

  • 使用官方Appium Docker镜像,避免环境不一致
  • 只在Merge Request时触发冒烟测试,不阻塞日常开发
  • 失败时自动上传日志和截图到S3(方便甩锅……啊不是,方便排查)

上线三个月,回归测试时间从3天压缩到2小时,产品经理看我的眼神都温柔了。上周五晚上他居然没在群里@我改需求,感动哭了。


给想搞自动化的同学几点建议

  1. 别追求100%覆盖:优先覆盖核心路径(登录、支付、主流程),边缘场景手动测更高效。
  2. 真机测试不能省:尤其涉及传感器、权限、性能的场景。
  3. 日志和截图是救命稻草:失败时没有上下文,debug能把你送走。
  4. 把它写进简历:不管是求职还是内部晋升,“主导/参与移动端自动化体系建设”都是硬核加分项。我面试时聊这个项目,面试官眼睛都亮了。

最后:技术之外的感悟

做这个项目之前,我对测试的理解停留在“点点点”。现在才明白,好的自动化不是替代QA,而是放大QA的价值。我们的测试同学现在不再做重复劳动,而是专注探索性测试和用户体验评估——这才是人该干的活。

至于我?简历确实更新了,不过暂时不跳槽了。因为老板说:“下个项目搞Web3钱包自动化,你来牵头?”……算了,继续炼丹吧,至少模型不会突然弹出权限弹窗。

彩蛋:如果你也在折腾移动端自动化,欢迎留言交流。或者,如果你司缺一个既会调参又会写测试脚本的“复合型人才”……简历已备好,随时可投 😉

评论 0

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