Xcode 16 中 Swift Testing 的参数化(Parameterized)机制趣谈

概述
我们之前曾在 《用接地气的例子趣谈 WWDC 24 全新的 Swift Testing 入门》系列博文以及《WWDC24(Xcode 16)中全新的 Swift Testing 使用进阶》博文中较为系统地介绍了今年 WWDC 24 中全新的 Swift Testing 测试系统。

不过 Swift Testing 的本领远不止于此!这里我们将会用它“最重量级”的特性之一 参数化(Parameterized) 让多输入样本测试易如反掌、收放自如。
在本篇博文中,您将学到如下内容:
- 概述
- 1. 传统多输入样本测试的弊端
- 2. Swift Testing 中全新的 Parameterized 机制
- 3. 对于可能抛出错误的测试也是不在话下!
- 4. 细粒度管控 Parameterized 中每个参数的测试
- 总结
利用 Swift Testing 中强大的 Parameterized 机制可以让秃头码农们的测试如虎添翼,那还等什么呢?
让我们马上开始测试吧!Let’s Testing!!!😉
1. 传统多输入样本测试的弊端
在以往的 XCTest 测试系统中,要想检测多个输入值的执行结果我们往往需要编写多个测试方法来一一验证。
enum ValidationError: Error {case valueTooSmallcase valueTooBigcase unknown
}struct Validator {static func validate(input: Int) throws(ValidationError) -> Bool {if input < 0 {throw .valueTooSmall} else if input > 100 {throw .valueTooBig} else {true}}
}
比如,上面我们实现了一个 Validator 验证器,并用它的 validate() 静态方法来验证输入值必须在 0 - 100 之间。注意,为了演示之目的我们在输入值超大或超小时抛出了错误。
在下面的代码中,我们期望输入值 5 是有效的:
@Test("验证 5 是否为有效输入")
func testCorrectValue() throws {#expect(try Validator.validate(input: 5), "期待 5 为有效输入")
}
照例,我们还要验证一下无效值是否能够顺利的抛出错误:
@Test("验证 -10 是非法输入")
func testTooSmall() throws {#expect(throws: ValidationError.valueTooSmall) {try Validator.validate(input: -10)}
}
如此这般,我们需要继续验证其它输入值的检测结果:比如 -10, 0, 15, 90, 100, 和 200 等等。照以往来说,此时我们要为每一个输入值写一个测试方法,或是将若干个测试放在一个测试方法中。这样做有一些讨厌的“坏味道”:
- 违反 KISS 和 DRY原则;
- 不适合测试的细粒度管控;
所以,我们该如何是好呢?
2. Swift Testing 中全新的 Parameterized 机制
所幸的是,在 Xcode 16 崭新的 Swift Testing 中我们有了一种更现代化的方法来解决它,这就是 Parameterized(参数化)机制:

从上面文档中可以看到,Swift Testing 的参数化机制其实就是 Test 宏构造器的一种重载形式。我们还可以看到,使用 Parameterized 机制的必备条件为:Swift 6+ 和 Xcode 16+。
回到 Validator 验证器的测试中,我们这回使用 Parameterized 机制来降服一下之前多个输入值的“桀骜不驯”:
@Test("验证一些有效的输入值",arguments: [0, 11, 20, 55, 90, 99, 100]
)
func testRejectsOutOfBoundsValues(input: Int) throws {#expect(try Validator.validate(input: input), "期待 \(input) 要有效哦 ;)")
}
现在,我们可以用同一个方法测试任意数量的输入值了。而且可以看到,其实参数化机制就是将多个输入值以参数数组的形式传入到测试方法里进行集中测试。
3. 对于可能抛出错误的测试也是不在话下!
在上面的代码中,我们仅仅测试了有效的输入值,那么对于无效的输入值我们还需要另外写一个参数化测试方法来“一蹴而就”吗?
答案是:没问题,但不需要!
我们完全可以将有效和无效的测试输入样本统统放到一起考量,即使它们可能抛出错误也“毫无压力”:
@Test("验证有效和无效的输入值",arguments: [(input: -10, expectedError: ValidationError.valueTooSmall),(input: 0, expectedError: nil),(input: 15, expectedError: nil),(input: 55, expectedError: nil),(input: 95, expectedError: nil),(input: 100, expectedError: nil),(input: 200, expectedError: ValidationError.valueTooBig),(input: 29352354, expectedError: ValidationError.valueTooBig),]
)
func testRejectsOutOfBoundsValues(input: Int, error: ValidationError?) throws {if let error {#expect(throws: error) {try Validator.validate(input: input)}} else {#expect(try Validator.validate(input: input), "期待 \(input) 要有效哦 ;)")}
}
从上面代码可以看到:我们将无效值和其对应期望抛出的错误打包到元组(Tuple)中,这样在测试方法中我们即可通过附加的实参取得该错误值并决定如何完成该输入值的测试。
当然,如果小伙伴们愿意的话我们仍然可以保持 testRejectsOutOfBoundsValues 测试方法只含有一个实参:
@Test("验证有效和无效的输入值",arguments: [(input: -10, expectedError: ValidationError.valueTooSmall),(input: 0, expectedError: nil),(input: 15, expectedError: nil),(input: 55, expectedError: nil),(input: 95, expectedError: nil),(input: 100, expectedError: nil),(input: 200, expectedError: ValidationError.valueTooBig),(input: 29352354, expectedError: ValidationError.valueTooBig),]
)
func testRejectsOutOfBoundsValues(condition: (value: Int, error: ValidationError?)) throws {if let error = condition.error{#expect(throws: error) {try Validator.validate(input: condition.value)}} else {#expect(try Validator.validate(input: condition.value), "期待 \(condition.value) 要有效哦 ;)")}
}
4. 细粒度管控 Parameterized 中每个参数的测试
使用 Parameterized 机制来规划 Swift Testing 不但能让海量样本的测试逻辑芟繁就简,而且更为“炸裂”的是我们现在可以:
- 一目了然的观察是哪几个输入值导致测试失败了;
- 继续单独测试任意输入值;
在下面的演示中,我们可以“鸟瞰”参数化方法中所有输入值测试的成功与否;我们可以一次性测试全部输入值,也可以单独测试某几个输入值。我们甚至可以重复测试某一参数值并设定测试结束条件:

看到这里,小伙伴们对 Swift Testing 是否更加“刮目相看”了呢?别再犹豫,马上在自己的项目中放手簪星曳月的使用它们吧!棒棒哒!💯
想要系统学习 Swift 的小伙伴们,欢迎到我的《Swift语言开发精讲》专栏来逛一逛哦:

- 《Swift 语言开发精讲》
总结
在本篇博文中,我们继续介绍了 Xcode 16 全新 Swift Testing 中的参数化(Parameterized)测试机制。有此神兵利器,相信小伙伴们在今后的单元测试中必将出奇制胜、手到擒来!
感谢观赏,再会吧!😎
相关文章:
Xcode 16 中 Swift Testing 的参数化(Parameterized)机制趣谈
概述 我们之前曾在 《用接地气的例子趣谈 WWDC 24 全新的 Swift Testing 入门》系列博文以及《WWDC24(Xcode 16)中全新的 Swift Testing 使用进阶》博文中较为系统地介绍了今年 WWDC 24 中全新的 Swift Testing 测试系统。 不过 Swift Testing 的本领远…...
Python自动化运维DevSecOps与安全自动化
Python自动化运维DevSecOps与安全自动化 目录 🛡️ DevSecOps概念与实践🔍 自动化安全扫描与漏洞修复🧰 基于Python的安全审计与合规性检查🐳 云平台与容器安全:基于Python的容器扫描工具⚠️ 自定义安全检测与漏洞修…...
2024下半年系统架构师考试【回忆版】
2024年11月10日,系统架构师考试如期举行,屡战屡败的参试倒是把北京的学校转了好几所。 本次考试时间 考试科目考试时间综合知识、案例分析8:30 - 12:30论文14:30 - 16:30 综合知识 1、1-1000以内包含5的数字个数 2、 案例分析 1、RESTful 对于前后…...
UE5.4 PCG 自定义PCG蓝图节点
ExecuteWithContext: PointLoopBody: 效果:点密度值与缩放成正比...
迁移学习相关基础
迁移学习 目标 将某个领域或任务上学习到的知识或模式应用到不同但相关的领域或问题中。 主要思想 从相关领域中迁移标注数据或者知识结构、完成或改进目标领域或任务的学习效果。 概述 Target data:和你的任务有直接关系的数据,但数据量少ÿ…...
华为云计算HCIE-Cloud Computing V3.0试验考试北京考场经验分享
北京试验考场 北京考场位置 1.试验考场地址 北京市海淀区北清路156号中关村环保科技示范园区M地块Q21楼 考试场选择北京,就是上面这个地址,在预约考试的时候会显示地址,另外在临近考试的时候也会给你发邮件,邮件内会提示你考试…...
数据分析——学习框架
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
量化交易系统开发-实时行情自动化交易-3.4.2.Okex行情交易数据
19年创业做过一年的量化交易但没有成功,作为交易系统的开发人员积累了一些经验,最近想重新研究交易系统,一边整理一边写出来一些思考供大家参考,也希望跟做量化的朋友有更多的交流和合作。 接下来聊聊基于Okex交易所API获取行情数…...
pytorch实现深度神经网络DNN与卷积神经网络CNN
DNN概述 深度神经网络DNN来自人脑神经元工作的原理,通过在计算机中逻辑抽象出多个节点,接收处理并向后传递信息,实现计算机的自我学习,类比结构见下图: 该方法通过预测输出与实际值的差异不断调整节点参数࿰…...
芯片测试-LDO测试
LDO测试 💢LDO的简介💢💢压降💢💢决定压降的主要因素💢 💢LDO的分类及原理💢💢PMOS LDO💢💢PMOS LDO工作过程💢💢PMOS LDO…...
期权懂|期权新手看过来:看跌期权该如何交易?
期权小懂每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 期权新手看过来:看跌期权该如何交易? 一、可以直接购买看跌期权: (1)选择预期下跌的标的资产。 (2&#…...
《深入浅出HTTPS》读书笔记(8):密码学Hash算法的分类
密码学Hash算法有很多,比如MD5算法、SHA族类算法,MD5早已被证明是不安全的Hash算法了,目前使用最广泛的Hash算法是SHA族类算法。 1)MD5 MD5是一种比较常用的Hash算法,摘要值长度固定是128比特。 MD5算法目前被证明已…...
大语言模型安全,到底是什么的安全
什么是AI安全 自ChatGPT问世以来,市场上涌现出了众多大型语言模型和多样化的AI应用。这些应用和模型在为我们的生活带来便利的同时,也不可避免地面临着安全挑战。AI安全,即人工智能安全,涉及在人工智能系统的开发、部署和使用全过…...
论文2—《基于柔顺控制的智能神经导航手术机器人系统设计》文献阅读分析报告
论文报告:基于卷积神经网络的手术机器人控制系统设计 摘要 本研究针对机器人辅助微创手术中定向障碍和缺乏导航信息的问题,设计了一种智能控制导航手术机器人系统。该系统采用可靠和安全的定位技术、7自由度机械臂以及避免关节角度限制的逆运动学控制策…...
试编写算法将单链表就地逆置(默认是带头节 点,如果是不带头节点地逆置呢?)
编写一个算法来就地逆置一个单链表。默认情况下,链表是带头节点的,但如果链表不带头节点,逆置的过程会有所不同。 第一步:定义逆置函数 根据题目中的“试编写算法将单链表就地逆置”,我们需要: 定义一个…...
FPGA学习笔记#3 Vitis HLS编程规范、数据类型、基本运算
本笔记根据笔者目前的项目确定学习目标,目前主要集中在Vitis HLS上,使用的Vitis HLS版本为2022.2,在windows11下运行,仿真part为xcku15p_CIV-ffva1156-2LV-e,从这一篇开始是HLS的学习进度,主要根据教程&…...
爬虫 - 二手交易电商平台数据采集 (一)
背景: 近期有一个需求需要采集某电商网站平台的商品数据进行分析。因此,我计划先用Python实现一个简单的版本,以快速测试技术的实现可能性,再用PHP实现一个更完整的版本。文章中涉及的技术仅为学习和测试用途,请勿用于商业或非法用…...
“成交量分布指标“,通过筹码精准锁定价格方向+简单找市场支撑压力位 MT4免费公式!
指标名称:成交量分布指标 版本:MT4 ver. 1.32 之前发布的市场分布图不少朋友反馈不错,希望获得其它版本。 这个版本只有MT4的,MT5可以看之前版本,链接: “市场分布图”,精准把握价格动向 更直…...
简记Vue3(四)—— 路由
个人简介 👀个人主页: 前端杂货铺 🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...
Python批量合并多个PDF
在日常工作中,处理和合并多个 PDF 文件是一个常见需求,尤其是在需要将大量文件整理成一个完整文档时。本文将详细介绍如何使用 Python 的 PyMuPDF 库来实现批量 PDF 文件合并,并提供针对大文件优化的解决方案。 安装 PyMuPDF 要使用 PyMuPD…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
