用接地气的例子趣谈 WWDC 24 全新的 Swift Testing 入门(二)

在这里插入图片描述

概述

从 WWDC 24 开始,苹果推出了全新的测试机制:Swift Testing。利用它我们可以大幅度简化之前“老态龙钟”的 XCTest 编码范式,并且使得单元测试更加灵动自由,更符合 Swift 语言的优雅品味。

在这里插入图片描述

在这里我们会和大家一起初涉并领略 Swift Testing 的测试之美。

在本篇博文中,您将学到如下内容:

  • 概述
  • 3. @Test 宏
    • 3.1 按条件启用和禁用测试
    • 3.2 使用 Tag 逻辑分组测试方法
    • 3.3 使用 arguments 避免重复测试
  • 总结

测试为先,质量为王!无测试,不软件!

那还等什么呢?Let’s testing!!!😉


3. @Test 宏

从上篇的示例代码中,我们应该可以体会到新 Swift Testing 的些许妙处。接下来我们着重谈谈其中几个常用的宏。

首先是 @Test 宏,我们可以使用它将任意方法变为可测试方法。我们还可以在类型(结构或类)内部使用它们以便将相关的测试“聚散成组”:

struct ModelTests {
    
    var model = Model.shared
    
    @Test("测试创建 Itmes")
    mutating func createItems() {
        model.createItems()
        #expect(!model.items.isEmpty, "应该成功创建若干 Items!")
    }
    
    @Test("测试删除所有 Item")
    mutating func delItem(){
        model.createItems()
        #expect(!model.items.isEmpty)
        model.deleteAllItems()
        #expect(model.items.isEmpty, "应该成功删除所有 Items!")
    }
}

在上面的代码中,我们将两个测试方法放到 ModelTests 结构里,从左边侧边栏的内容可以看到,这使得它们形成了一个新的“测试组” ModelTests:

在这里插入图片描述

这样做的好处主要有两个:

  1. 将测试方法分门别类,便于管理;
  2. 可以将测试的构造和析构操作统一放到类型对象的析构和析构方法中去,避免冗余;

除此之外,利用 @Test 宏的不同重载形式,我们还可以实现一些有趣的测试特性。

3.1 按条件启用和禁用测试

我们可以利用 enabled 这个@Test ConditionTrait 来实现按指定条件开启和禁止对应的测试方法。

在这里插入图片描述

如下代码所示,我们仅在 testSettings.needTestDeleting 属性值为 true 的情况下才进行 Item 的删除测试:

class TestSettings {
    static let shared = TestSettings()
    
    var needTestDeleting = false
}

let testSettings = TestSettings.shared

struct ModelTests {
    
    var model = Model.shared
    
    @Test("测试创建 Itmes")
    mutating func createItems() {...}
    
    // 仅在 testSettings.needTestDeleting 为真时使能 delItem 测试
    @Test("测试删除所有 Item", .enabled(if: testSettings.needTestDeleting))
    mutating func delItem(){
        
        model.createItems()
        #expect(!model.items.isEmpty)
        model.deleteAllItems()
        #expect(model.items.isEmpty, "应该成功删除所有 Items!")
    }
}

当对应条件值为假时,Xcode 会跳过对应的 delItem() 测试方法:

在这里插入图片描述

当然,如果我们希望的话还可以使用 disabled 条件彻底禁止某个测试方法:

@Test("测试删除所有 Item", .disabled("可能会导致系统挂起的找不到北"))
    mutating func delItem(){...}

3.2 使用 Tag 逻辑分组测试方法

除了通过结构或类来“物理的”组合测试方法以外,我们还可以通过标签(Tag)以逻辑的方式安排类似的测试。

为了达到这一目的,我们首先必须实现一个遵守 CodingKey 协议的实体类型:

struct MyCoding: CodingKey {
    
    var codingValue: String
    
    init?(intValue: Int) {
        codingValue = "\(intValue)"
    }
    
    init?(stringValue: String) {
        codingValue = stringValue
    }
    
    var stringValue: String {
        codingValue
    }
    
    var intValue: Int? {
        Int(codingValue)
    }
}

当然,我们也可以让现有类型(比如 String)遵守 CodingKey 协议来简化代码。

接着为 Tag 类型扩展我们自定义的标签:

extension Tag {
    static let createItem = Tag(codingKey: MyCoding(stringValue: "CreateItem")!)!
}

最后,在对应的测试方法上设置指定的 Tag 即可:

@Test(.tags(.createItem))
func checkItemsCount() async throws {
    var model = Model.shared
    model.createItems()
    #expect(model.items.count == 3)
}

struct ModelTests {
    
    var model = Model.shared
    
    @Test("测试创建 Itmes", .tags(.createItem))
    mutating func createItems() {...}
    
    @Test("测试删除所有 Item", .disabled("可能会导致系统挂起找不到北"))
    mutating func delItem(){...}
}

现在,我们可以按标签(例如 createItem)来组织和集中测试海量 Testing 方法啦:

在这里插入图片描述

3.3 使用 arguments 避免重复测试

@Test 还有一个非常有用的特性:简化测试重复代码。在下面的实现中我们就使用 arguments 特性向 mentionedContinentCounts 方法传入了若干测试参数,从而仅用一个测试方法就搞定了所有相似的测试:

struct VideoContinentsTests {

    @Test("Number of mentioned continents", arguments: [
        "A Beach",
        "By the Lake",
        "Camping in the Woods",
        "The Rolling Hills",
        "Ocean Breeze",
        "Patagonia Lake",
        "Scotland Coast",
        "China Paddy Field",
    ])
    func mentionedContinentCounts(videoName: String) async throws {
        let videoLibrary = try await VideoLibrary()
        let video = try #require(await videoLibrary.video(named: videoName))
        #expect(!video.mentionedContinents.isEmpty)
        #expect(video.mentionedContinents.count <= 3)
    }
}

限于篇幅,关于 Swift Testing 参数化测试(Refactor several similar tests into a parameterized @Test function)的介绍这里就不再展开说明了。

想要详细了解相关内容的小伙伴们请到之前列出的 WWDC 24 官方 Testing 开发视频中进一步观赏吧。

在下一篇博文中,我们将介绍 Swift Testing 另一个不可或缺的宏:#expect,不见不散!


想要系统学习 Swift 的小伙伴们,请来我的《Swift语言开发精讲》专栏逛一逛哦:

在这里插入图片描述

  • 《Swift 语言开发精讲》

总结

在本篇博文中,我们讨论了 Swift Testing 测试中至关重要的宏:@Test,我们随后还分别介绍了它的 3 种重载形式,小伙伴们值得拥有。

感谢观赏,我们下一篇见!😎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/908944.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python的自然语言生成与对话系统介绍

1. 背景介绍 自然语言生成(Natural Language Generation&#xff0c;NLG)和对话系统是人工智能领域的重要研究方向。NLG 涉及将计算机理解的信息转换为自然语言文本&#xff0c;而对话系统则涉及计算机与用户之间的自然语言交互。Python 作为一种易于学习、易于使用的编程语言…

HarmonyOS NEXT 应用开发实战(十、从零设计一款个人中心页面详细示例)

随着HarmonyOS的不断发展&#xff0c;越来越多的开发者开始关注这个平台上的应用开发。本篇文章将详细讲解如何从零开始设计一款个人中心页&#xff0c;并在代码中实现其相关功能。 1. 项目结构设计 首先&#xff0c;我们需要设计一个合理的项目结构。我们将个人中心页面分为几…

Node.js 入门指南:从零开始构建全栈应用

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;node.js篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来node.js篇专栏内容:node.js-入门指南&#xff1a;从零开始构建全栈应用 前言 大家好&#xff0c;我是青山。作…

我们来学mysql -- 连接(原理版)

我们来学mysql -- 连接 题记两张表驱动表 题记 回到初学者的视角&#xff0c;navicat或命令窗口&#xff0c;呈现一行行数据&#xff0c;类比为excel工作薄更是深入人心通过join将多表的记录关联起来&#xff0c;这似乎也没啥问题只是好像是那么回事&#xff0c;又…似乎有想说…

ssm校园二手交易管理系统+vue

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码看文章最下面 需要定制看文章最下面 目 录 1 绪论 1 1.1 选题背景 1 1.2 选题意义 1 1.3 研究内容 2 2 系统开发技术 3 2.1 MySQL数…

2024年前三季度币安、OKX等五大交易所上币表现分析

随着加密市场竞争的加剧&#xff0c;头部交易所逐渐在上币策略、代币选择、交易活跃度等方面采取了不同的应对策略。Animoca Digital Research近期发布的一份报告&#xff0c;通过对币安、OKX、Bitget、KuCoin和Bybit五大交易所2024年前三季度的上币情况进行了详细分析。本文将…

Nature文章《deep learning》文章翻译

这篇文章是对Nature上《deep learning》文章的翻译。原作者 Yann LeCun, Yoshua Bengio& Geoffrey Hinton。 这篇文章的中心思想是深入探讨深度学习在机器学习中的革命性贡献&#xff0c;重点介绍其在特征学习、监督学习、无监督学习等方面的突破&#xff0c;并阐述其在图…

使用 RabbitMQ 有什么好处?

大家好&#xff0c;我是锋哥。今天分享关于【使用 RabbitMQ 有什么好处&#xff1f;】面试题。希望对大家有帮助&#xff1b; 使用 RabbitMQ 有什么好处&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 RabbitMQ 是一种流行的开源消息代理&#xff0c;广…

Scrapy链接MongoDB数据库

本文章是在Scrapy入门-CSDN博客的基础上改写的代码。 1.声明采集目标 打开mySpider/mySpider1/items.py文件&#xff0c;修改MyspiderItem类为AIspiderItem&#xff1a; class AIspiderItem(scrapy.Item): title scrapy.Field() url scrapy.Field() date scrapy.Field() 2…

Qt项目实战:红绿灯小程序

目录 一.初始化对象 二.捕获并处理特定的事件 三.自定义绘制方法 四.绘制外部边框 五.绘制内部边框 六.绘制按钮的背景色 七.绘制覆盖层&#xff08;高光效果&#xff09; 八.效果 九.代码 1.h 2.cpp 一.初始化对象 1.设置文本、颜色、边框和背景色等默认值。 2.安…

ReactPress 是什么?

ReactPress Github项目地址&#xff1a;https://github.com/fecommunity/reactpress 欢迎Star。 ReactPress 是什么&#xff1f; ReactPress 是使用React开发的开源发布平台&#xff0c;用户可以在支持React和MySQL数据库的服务器上架设属于自己的博客、网站。也可以把 ReactP…

萤石私有化设备视频平台EasyCVR视频融合平台如何构建农业综合监控监管系统?

现代农业的迅速发展中&#xff0c;集成监控管理系统已成为提高农业生产效率和优化管理的关键工具。萤石私有化设备视频平台EasyCVR&#xff0c;作为一个具有高度可扩展性、灵活的视频处理能力和便捷的部署方式的视频监控解决方案&#xff0c;为农业监控系统的建设提供了坚实的技…

PG数据库 jsonb字段 模糊查询

背景&#xff1a; 项目由于多语言的设计&#xff0c;将字段设置成json字段类型&#xff0c;同时存储中文和英文 页面上通过输入框实现模糊的查询 一、表结构&#xff1a;name字段设置jsonb类型 二、表数据 3、Mybatis编写sql select pp.name ->>zh-CN as pmsProductNam…

Chrome 插件怎么安装与下载?超详细

原文链接&#xff1a; https://www.chajianxw.com/tutorial/how-to-install-chrome-plugin.html 前言 国内因为无法访问 Chrome 应用商店的缘故&#xff0c;导致很多优秀的扩展程序无法正常下载与安装。本文将手把手教你如何通过离线安装Chrome 插件&#xff0c;全文图文讲解…

【软服之家-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

深入解析:人工智能与机器学习

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 深入解析&#xff1a;人工智能与机器学习 深入解析&#xff1a;人工智能与机器学习 深入解析&#xff1a;人工智能与机器学习 人…

React 组件生命周期与 Hooks 简明指南

文章目录 一、类组件的生命周期方法1. 挂载阶段2. 更新阶段3. 卸载阶段 二、函数组件中的 Hooks1. useState2. useEffect3. useContext4. useReducer 结论 好的&#xff0c;我们来详细讲解一下 React 类组件的生命周期方法和函数组件中的钩子&#xff08;hooks&#xff09;。 …

MySQL约束管理

介绍 MySQL约束管理是指在MySQL数据库中定义和管理数据约束的过程。数据约束用于维护数据的完整性和一致性&#xff0c;确保数据在表中的存储符合特定的规则。通过约束&#xff0c;可以防止不符合要求的数据被插入或更新&#xff0c;从而保护数据库的质量。 约束管理的主要内…

无功功率的电流值是有效值吗?

无功功率的电流值通常指的是无功电流的有效值&#xff08;RMS值&#xff09;。为了更好地理解这个问题&#xff0c;先来区分无功功率和有功功率的概念&#xff1a; 1、无功功率的定义 无功功率&#xff08;Q&#xff09;&#xff1a;无功功率是由电感和电容共同作用产生的功率…

亲测解决adobe genuine service alert

这个问题是由于app里面有adobe genuine service&#xff0c;这个软件出问题导致&#xff0c;解决方法是卸载它。 环境 Win 11 adobe acrobat 解决方法 卸载adobe genuine service。 参考 https://www.reddit.com/r/GenP/comments/mmw9qp/comment/guh5pk4/?utm_sources…