请写一篇关于【iOS自动化测试:XCTest框架详解】的技术文章
被裁后接外包的全栈开发,和老婆异地,周末才能见面。这是我的第17个外包项目,也是我重新找回节奏的关键一战。
去年十月的一个周五晚上,9点42分,我坐在出租屋的电脑前,盯着屏幕上跳动的红色失败用例,手指无意识地敲着机械键盘——咔哒、咔哒、咔哒。窗外是杭州下沙的夜色,楼下烧烤摊还在冒烟,隔壁情侣在吵架,而我,刚被裁员三个月,正为一个iOS外包项目的交付 deadline 焦头烂额。
手机震动了一下,是我老婆发来的消息:“今天又加班?别太拼了,周末见。”
我回了个“嗯”,然后深吸一口气,把脸埋进手掌——我真的快撑不住了。
从大厂到自由职业:一场猝不及防的“毕业”
事情得从今年七月说起。我在一家中型互联网公司做了三年全栈开发,月薪15k,房租3500,生活稳定但毫无波澜。直到那个周一晨会,HR把我叫进小会议室,递来一杯咖啡,说:“公司战略调整,你被优化了。”
“优化”这个词,现在听来还是有点讽刺。那天回家路上,我一直在想:房贷怎么办?异地恋怎么维持?她在北京做产品经理,我原计划年底攒够首付就去北京找她团聚。
失业第一个月,我投了67份简历,面了12家公司。有一家问得很直接:“你会iOS自动化测试吗?我们项目要用XCTest做UI回归。”
我支支吾吾答不上来,只说“会写单元测试”。结果可想而知——挂了。
那晚我和老婆视频,她看我脸色不对,问:“是不是面试又没成?”
我点点头,声音有点哑:“感觉自己的技术栈太杂,啥都会一点,但都不精。”
她沉默了几秒,说:“要不……试试接外包?先稳住收入,再补短板?”
于是,我注册了三个外包平台,开始接单。第一个项目是给一个电商App加个Springboot后台接口,报价8000,两周交付。虽然累,但至少银行卡里有了进账。第二个、第三个……慢慢有了口碑,客户开始主动找上门。
直到上个月,一个老客户甩给我一个新需求:“我们有个iOS App要做自动化测试,主要是登录、下单、支付这几个核心路径。你搞过XCTest吗?”
我其实没搞过。但为了拿下这个2.2w的项目,我硬着头皮说:“做过,没问题。”
硬着头皮啃XCTest:从“红条满屏”到“绿灯通行”
接下项目后,我才真正意识到自己踩了多大的坑。
XCTest是Apple官方的测试框架,集成在Xcode里,支持单元测试(Unit Test)和UI测试(UI Test)。听起来简单,但真上手才发现水有多深。
我打开客户的项目代码,发现他们连基本的测试结构都没有。更糟的是,UI全是用Storyboard拖的,没有明确的accessibilityIdentifier——这意味着我连元素都定位不到!
第一周,我的测试用例全是红的。
不是“element not found”,就是“timeout waiting for element”。有一次凌晨三点,我对着模拟器里卡死的登录按钮,差点把键盘砸了。
但我知道不能放弃。这项目要是黄了,下个月房租都成问题。而且,这可能是我补齐“移动端测试”能力的关键机会。
于是我开始系统性地补课:
给所有UI控件加上accessibilityIdentifier
比如登录按钮:loginButton.accessibilityIdentifier = "loginButton"这样在UI测试里就能用
app.buttons["loginButton"]精准定位。用XCTestExpectation处理异步操作
比如网络请求后的页面跳转:let expectation = XCTestExpectation(description: "Login success") DispatchQueue.main.asyncAfter(deadline: .now() + 2) { XCTAssertTrue(app.staticTexts["Home"].exists) expectation.fulfill() } wait(for: [expectation], timeout: 10)封装公共方法,避免重复代码
我写了个TestHelper.swift:class TestHelper { static func login(username: String, password: String, app: XCUIApplication) { app.textFields["usernameField"].tap() app.textFields["usernameField"].typeText(username) app.secureTextFields["passwordField"].tap() app.secureTextFields["passwordField"].typeText(password) app.buttons["loginButton"].tap() } }结合持续集成(CI)跑测试
客户用的是GitLab CI,我在.gitlab-ci.yml里加了:test_ios: script: - xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 14'
三周后,测试覆盖率从0%提升到68%,核心路径全部通过。交付那天,客户发来消息:“兄弟,牛啊!比我们之前外包的团队靠谱多了。”
那一刻,我瘫在椅子上,眼眶有点热。不是因为钱,而是因为——我终于能靠自己的技术吃饭了。
面试题挑战:当XCTest遇上Springboot
有意思的是,就在上周,我又去面了一家公司。面试官是个戴黑框眼镜的架构师,开场就扔出一道题:
“假设你有一个Springboot后台,一个iOS前端。如何设计端到端的自动化测试,确保登录功能从API到UI都正常?”
我笑了。这不就是我最近干的事吗?
我答:“我会分三层做:
- Springboot层:用JUnit + Mockito测Controller和Service逻辑;
- 接口层:用Postman或RestAssured验证API返回;
- iOS层:用XCTest做UI测试,模拟真实用户操作。”
我还补充:“关键是数据隔离。比如测试账号要独立,不能污染生产数据。我会在Springboot里加一个@Profile("test")的配置,自动创建测试用户;iOS测试时用这个账号登录。”
面试官点点头:“不错,考虑得很全。”
后来HR打电话来谈薪资,开到了22k。比裁员前高了近50%。我犹豫了一下,还是婉拒了——我现在接外包一个月也能赚这个数,还能自由安排时间,周末飞北京看老婆。
异地恋、自由职业与技术人的尊严
很多人问我:“自由职业不稳定,不怕吗?”
怕,当然怕。尤其是半夜改bug、客户催进度、银行余额告急的时候。
但我也越来越清楚:技术人的价值,不在工位上,而在解决问题的能力里。
XCTest只是工具,Springboot也只是框架。真正让我翻身的,是那种“死磕到底”的劲儿——就像上周五晚上,我一边调试UI测试,一边和老婆视频:“等这个项目结束,我就能多存点钱,争取明年搬去北京。”
她说:“你现在的状态,比在大厂时好多了。”
我说:“因为我知道,每行代码都在为我们的未来打工。”
给同行的几点建议
如果你也在迷茫,或者正准备入坑iOS自动化测试,分享几点血泪经验:
别怕从零开始
XCTest文档其实很友好,Apple的官方示例(比如UI Testing in Xcode)值得反复看。测试不是“额外工作”,而是“质量保险”
客户最怕线上出bug。一套稳定的自动化测试,能让你在交付时底气十足。全栈思维很重要
我之所以能搞定那个“Springboot + iOS”端到端测试,是因为前后端都懂。建议iOS开发者也学点后端,反之亦然。保持输出,建立个人品牌
我现在每周写一篇技术复盘,发在掘金和知乎。不仅帮别人避坑,也让自己思考更系统。
写在最后
凌晨1点,我又一次提交了测试代码。CI流水线跑完,绿色的✓一个个亮起。窗外安静了,烧烤摊收了,情侣也不吵了。
我关掉电脑,给老婆发了条消息:“下周六,我去北京。给你带西湖藕粉。”
然后躺在床上,想起半年前被裁那天的慌乱。
现在回头看,那不是终点,而是我真正掌握自己职业生涯的起点。
技术这条路,没有铁饭碗,但有真本事。
只要你愿意动手、愿意学习、愿意在深夜和红条死磕——
你就永远有饭吃,有路走,有爱可守。
共勉。

评论 0