从加班写测试到用XCTest自动跑:一个考公程序员的iOS自动化自救指南

端口被占用
2026-05-13 04:00
阅读 1509

上周五晚上十点,我盯着屏幕上密密麻麻的UI操作步骤文档,手边的冰美式已经凉透。产品经理刚发来第7版“紧急上线”需求,要求下周三前完成全部回归测试——而我们组唯一的测试同事正在休婚假。

那一刻我真的想砸电脑。

但转念一想,不行,这台MacBook Pro是我攒了半年工资买的,砸了心疼。而且再过三个月就要参加省考了,得稳住心态。于是深吸一口气,打开终端,决定把去年双11就该搞的iOS自动化测试捡起来。

作为一名在互联网公司卷了三年多的前端程序员(对,就是那个天天被说“切页面的”岗位),我对交互和动画一直比较上头。但说实话,写测试脚本这事,我一直拖着没碰——总觉得这是QA的事,跟我这个“创造者”没啥关系。直到最近项目频繁线上bug,老板在周会上阴阳怪气地说“你们开发是不是觉得自己写的代码永远不出错?”,我才意识到:自动化测试不是负担,是保护自己的盔甲

为什么选XCTest?

其实市面上自动化方案不少:Appium、EarlGrey、KIF……但我最终还是回到了Apple亲儿子XCTest。原因很简单:

  • 原生支持,跟Xcode无缝集成
  • 写Swift的同学不用额外学新语言
  • 审核时不会因为用了第三方测试框架被拒(吃过亏)
  • 对SwiftUI的支持越来越好了

最关键的是——我不想再装一堆Java环境、Node.js依赖了。在Mac上敲代码已经够清爽了,干嘛非要用Windows那一套笨重的东西?

上手XCTest:比想象中简单

新建一个iOS项目后,Xcode默认就会带一个YourAppUITests target。进去一看,模板代码长这样:

import XCTest

class YourAppUITests: XCTestCase {

    override func setUpWithError() throws {
        continueAfterFailure = false
        XCUIApplication().launch()
    }

    func testExample() throws {
        // UI tests must launch the application that they test.
        let app = XCUIApplication()
        // Use XCTAssert and related functions to verify your tests produce the correct results.
    }
}

别被XCUIApplication()吓到,它其实就是你正在测试的那个App实例。你可以像操作真实用户一样去点按钮、输文字、滑动页面。

举个实际例子:我们有个登录页,需要输入手机号和验证码。手动测一次就得30秒,一天测20轮?命都搭进去了。

于是我写了这段自动化脚本:

func testLoginFlow() {
    let app = XCUIApplication()
    
    // 等待登录页出现
    let phoneField = app.textFields["phoneInput"]
    XCTAssertTrue(phoneField.waitForExistence(timeout: 5))
    
    // 输入手机号
    phoneField.tap()
    phoneField.typeText("13800138000")
    
    // 点击获取验证码(假设按钮accessibilityIdentifier是"getVerifyCode")
    app.buttons["getVerifyCode"].tap()
    
    // 等待验证码输入框可编辑
    let codeField = app.textFields["verifyCode"]
    XCTAssertTrue(codeField.waitForExistence(timeout: 3))
    codeField.tap()
    codeField.typeText("123456")
    
    // 点击登录
    app.buttons["loginButton"].tap()
    
    // 验证是否跳转到首页(比如首页有个tab叫"homeTab")
    XCTAssertTrue(app.tabBars.buttons["homeTab"].waitForExistence(timeout: 10))
}

关键点来了:一定要给UI元素设置accessibilityIdentifier
别偷懒用label或placeholder去定位,那些文字可能变,但identifier是你自己定的,稳如老狗。

// 在你的SwiftUI View里这么写
TextField("请输入手机号", text: $phoneNumber)
    .accessibilityIdentifier("phoneInput")

Button("获取验证码") {}
    .accessibilityIdentifier("getVerifyCode")

踩过的坑:那些让我半夜惊坐起的瞬间

坑1:异步操作等不到

第一次跑的时候,验证码按钮点了没反应。查了半天发现网络请求是异步的,脚本执行太快,还没收到响应就往下走了。

解决方案:用XCTWaiter或者更简单的——加等待:

let expectation = XCTestExpectation(description: "等待验证码发送成功")
// 模拟网络回调后 fulfill expectation
wait(for: [expectation], timeout: 10)

但说实话,这种写法太啰嗦。后来我学会了用waitForExistence配合合理的timeout,大部分场景够用了。

坑2:真机 vs 模拟器行为不一致

有次在模拟器跑得好好的,一上真机就崩。原因是模拟器键盘是软键盘,而真机连了蓝牙键盘……导致typeText失效。

解决方法:统一用setValue直接设值,绕过键盘输入:

phoneField.setValue("13800138000", for: .value)

不过要注意,这招只适用于测试,不能用于生产代码(会被App Store拒)。

坑3:测试数据污染

最开始我把测试账号写死在脚本里,结果某天产品改了登录逻辑,所有测试全挂。后来学乖了——用独立的测试环境 + 动态生成测试账号

现在我们的CI流程里会先调一个内部接口创建临时用户,拿到token后再跑UI测试,彻底隔离生产数据。

AI提效:别傻傻手写所有用例

说到这儿,必须提一句:别试图手写100%的测试用例。我之前就是太较真,想覆盖所有路径,结果写了两周还在搭框架。

后来试了几个AI工具,发现真香:

  • MCP(Mobile Cloud Platform):我们公司自研的移动测试平台,能自动录制用户操作并生成XCTest脚本。虽然生成的代码有点啰嗦,但至少省了80%的体力活。
  • Moltbot:一个开源的iOS测试辅助工具,可以智能识别页面元素并推荐accessibilityIdentifier命名,对我这种命名困难症太友好了。
  • 文心一言:别笑!有次我卡在一个手势操作上(需要双指缩放地图),直接把报错信息贴给文心一言,它居然给出了正确的XCUIElement手势API用法,比翻Apple文档快多了。

当然,AI不是万能的。它生成的代码往往缺乏边界条件处理,比如网络超时、弹窗拦截等。但作为初稿,效率提升非常明显。我现在的工作流是:AI生成骨架 → 手动补充异常处理 → 加入断言验证

实战效果:从每天2小时到5分钟

这套自动化跑起来后,最直观的变化是——我不用再周末加班测回归了!

以前每次发版前,光登录、注册、支付这几个核心路径就得手动跑一个多小时。现在CI流水线里加一行:

xcodebuild test -workspace YourApp.xcworkspace -scheme YourApp -destination 'platform=iOS Simulator,name=iPhone 15' -enableCodeCoverage YES

5分钟后,测试报告自动发到钉钉群,附带截图和失败原因。老板看了都说“这届程序员终于开窍了”。

更重要的是,线上P0级bug少了60%。那些“只在特定机型出现”的玄学问题,现在都能在合并代码前被自动化拦住。

给想上岸程序员的一点真心话

我知道很多人觉得:“我都准备考公了,还折腾这些干啥?”

但我想说:技术能力是你最后的退路。万一笔试没过,或者面试被刷,你总得有口饭吃。而且公务员考试越来越卷,很多岗位明确要求“有软件开发经验”,你这些实战项目,写在简历上就是加分项。

再说了,搞自动化测试这件事本身,就是在训练你的系统性思维——怎么设计用例?如何解耦依赖?怎样保证稳定性?这些能力,不管是写代码还是做行政,都用得上。

所以别躺平,哪怕每天只花半小时,把重复劳动自动化掉。省下来的时间,既可以刷行测题,也能陪对象看场电影。何乐不为?


最后附一张我们团队现在的测试覆盖率对比(纯文字版,毕竟不能插图):

测试类型 自动化前 自动化后 提升
核心路径UI测试 30% 95% +65%
回归测试耗时 2h/次 8min/次 -93%
线上严重bug 4.2个/月 1.7个/月 -59%

数据不会骗人。如果你也在被重复测试折磨,不妨试试XCTest。它可能不是最强大的,但对Apple生态开发者来说,足够好用,足够省心

好了,写完这篇博客,我也该去刷申论了。希望明年此时,我已经坐在体制内的工位上,悠闲地喝着保温杯里的枸杞茶——但电脑里,依然跑着整洁高效的代码。

评论 0

最热最新
暂无评论
端口被占用Lv.1
0
影响力
0
文章
0
粉丝