Swift 6.2 列传(第十七篇):钟灵的“雷电蟒”与测试附件

摘要 :一个失败的测试报告,如果只写着"某某参数错误",那和一张"失物招领"有什么区别?Swift Testing 新增的 Attachments(附件)功能(ST-0009),就像是给失败的测试现场,打上了一个**"现场取证包"**,直接将调试日志和关键数据附着在报告上,让 Bug 无所遁形。

0️⃣ 🐼 序章:万劫谷的"失灵"现场

万劫谷,一个充满了陷阱和奇门遁甲的虚拟测试环境。

大熊猫侯佩正在谷中寻找他那四根宝贝竹笋的踪迹(它们现在安全地储存在 InlineArray 里),一路上他习惯性地摸了摸头顶,确认自己的黑毛依然茂密,头绝对不秃

他身边站着一个活泼可爱的绿衫少女,正是钟灵 。钟灵的特点是天真烂漫,喜欢饲养各种"小宠物",尤其是她那条能放出电流的"雷电蟒"(现在是她编写的 Character Struct 数据模型)。

"侯大哥,你看!"钟灵指着屏幕上的测试报告,气得直跺脚,"我的测试又失败了!它明明应该生成一个名为 Rem 的角色,结果生成了 Ram!报告上只写了预期值和实际值,可是这个失败的 Ram 角色内部状态到底是什么?它的 UUID 是多少?我完全不知道!"

侯佩叹了口气:"这就是测试的黑箱困境 。失败的报告,就像是你看到一只断了腿的兔子,但不知道它是在哪条路上、被谁咬伤的。我们得找到现场遗留的物证。"

在本次大冒险中,您将学到如下内容:

  • 0️⃣ 🐼 序章:万劫谷的"失灵"现场
  • 1️⃣ 📦 驯服数据:Attachable 协议的契约
  • 2️⃣ 📝 现场取证:Attachment.record() 的铁律
  • 3️⃣ 🚧 侠客的遗憾:现阶段的不足
  • 4️⃣ 🐼 尾声:条件判断的"外功"与"内力"

钟灵急道:"对!我要把我的'雷电蟒'(数据模型)的全部信息,直接打包塞进这个失败报告里!(Swift Testing: Attachments)"


1️⃣ 📦 驯服数据:Attachable 协议的契约

要让数据能够被 Swift Testing 系统识别并打包,它必须遵守新的"江湖规矩":Attachable 协议。

侯佩指导钟灵,将她那可爱的"雷电蟒"数据模型进行武装升级:

swift 复制代码
import Foundation
import Testing 

// 钟灵的角色结构体,它就是那条"雷电蟒"
struct Character: Codable, Attachable { 
    var id = UUID() // 关键的内部状态,比如角色的唯一标识符
    var name: String
}

侯佩解释道:"Attachable 协议就像是你给你的宠物签订了一份'随行契约'。只要有了这个契约,系统就知道在关键时刻,应该如何'捕捉'和'打包'它。"

🔑 技术关键点:Codable 的加持 注意,这个 Character 结构体不仅遵循了 Attachable,还遵循了 Codable。对于像结构体这样的自定义数据类型,Swift Testing 会利用 Codable 的能力,将其实例自动编码DataString 格式,然后再进行附加。这样才能确保数据是有头有脸、完整地出现在报告中。

2️⃣ 📝 现场取证:Attachment.record() 的铁律

现在,钟灵只需要在她的生产代码(Production Code)中生成她的角色:

swift 复制代码
// 生产代码:生成一个新角色
func makeCharacter() -> Character {
    // 默认生成一个名叫 "Ram" 的角色
    Character(name: "Ram")
}

然后,在测试代码中,无论测试是成功还是失败,她都要确保这个角色的所有状态,都被系统记录下来:

swift 复制代码
@Test func defaultCharacterNameIsCorrect() {
    let result = makeCharacter()
    
    // 💔 测试失败断言:预期 Rem,实际 Ram
    #expect(result.name == "Rem") 

    // 🎒 关键步骤:记录附件!
    // 将整个 result 实例附着到本次测试结果中,并命名为 "Character"
    Attachment.record(result, named: "Character") 
}

"太神了!"钟灵惊呼道,"当这个测试运行失败时,Xcode 就会自动将这个 result 实例的 JSON 编码数据,直接显示在测试报告的旁边!我一眼就能看到这个失败的 Ram 角色的 UUID 是多少,它的内部状态是不是被某个毒药(Bug)污染了!"

侯佩点头:"这就叫 '证据确凿' 。以前你只能 望洋兴叹 ,现在你可以 一目了然。"

3️⃣ 🚧 侠客的遗憾:现阶段的不足

侯佩作为精通技术的工程师,也指出了这一功能在 Swift 6.2 版本的些许遗憾。

  • 🚫 图像缺失症: "目前,Swift Testing 尚不支持附加图像(Image),"侯佩遗憾地说,"这就像你抓到了一个间谍,却不让你拍下他的照片。如果我做 SwiftUI 界面测试,失败了却不能附上截图,那会让人非常抓狂。"
  • ♻️ 生命周期控制的缺席: "另一个遗憾是,它不像 XCTest 的同类功能那样,支持生命周期控制(Lifetime Controls)。"

"生命周期控制是什么?"钟灵好奇地问。

"就是如果你的测试成功了,系统可以自动删除 你附加的这些日志文件和数据。这样可以保持测试环境的轻量化。现在嘛,你成功了,这些文件还是会留在那,徒增烦恼。"

4️⃣ 🐼 尾声:条件判断的"外功"与"内力"

解决了附件问题,钟灵的测试调试效率提升了百倍。但她很快又遇到了新的困惑。

"侯大哥,我的宠物'雷电蟒'需要在不同的硬件环境(例如 M1 芯片和 Intel 芯片)上运行不同的代码。Swift Testing 有一个很方便的功能叫做 ConditionTrait,可以用来定义'只在 M1 上运行'的测试条件。"

侯佩点头:"是的,ConditionTrait 是测试的'内功',决定测试是否应该被执行。"

钟灵苦恼道:"但是,我能不能在非测试函数 (Non-test function),比如我的生产代码里,也引用和判断这个'内功'?比如,我想写一段普通的函数,判断'我现在是不是在 M1 芯片上运行?',并根据结果调整代码逻辑。"

侯佩眼中闪过一丝精光,他知道,钟灵提出的需求,已经触及到了 Swift Testing 的深层奥秘。

"钟灵姑娘,你提出了一个跨越测试与生产代码边界 的哲学问题。你需要的不是附件,而是将测试的'内功心法',转化为人人可用的'外功'招式。"

(欲知后事如何,且看下回分解:Swift Testing: Public API to evaluate ConditionTrait ------ 如何在普通函数中,运用测试框架的'条件判断'心法。)

相关推荐
大熊猫侯佩2 小时前
App 暴毙现场直击:如何用 MetricKit 写一份完美的“验尸报告”
app·xcode·apple
卓码软件测评5 小时前
软件首版次认定测试机构:【Apifox与UMI框架结合:实现OpenAPI规范与Mock服务的自动化流水线】
测试工具·ci/cd·性能优化·单元测试·测试用例
虫小宝7 小时前
企业微信API接口对接中Java后端的模拟测试(Mock)与单元测试实战技巧
java·单元测试·企业微信
东坡肘子7 小时前
AT 的人生未必比 MT 更好 -- 肘子的 Swift 周报 #118
人工智能·swiftui·swift
黄金贼贼1 天前
2026最新java单元测试json校验器
java·单元测试·json
帅次1 天前
从开发到部署:软件实现、测试与交付全流程核心技术解析
功能测试·单元测试·测试用例·集成测试·压力测试·模块测试·安全性测试
njsgcs2 天前
Swift playground 网页刷新切换随机页面的网页查看器WebKit
swift
iOS阿玮3 天前
“死了么”App荣登付费榜第一名!
uni-app·app·apple
叶落无痕524 天前
Electron应用自动化测试实例
前端·javascript·功能测试·测试工具·electron·单元测试