Tag: 单元测试

使用依赖注入来测试UIViewController

大家好,当我们开始编码以创建需要其他对象才能工作的对象时,这是很常见的,例如在Car类中,需要Person对象来启动引擎和驱动器( starEngine和drive是需要Person实例的假设方法)。 所以我们可以说Car需要一个Person来工作。 上面的代码向我们展示了Jhon正在驾驶我们的汽车,只有Jhon可以做到! 因为每个Car对象都会创建一个名为Jhon的Person的实例。 但是,如果玛丽想开车怎么办? 我们如何重写该代码以让Mary开车? 我们可以将一个Person传递到我们的Car ,使其可用于Person任何实例,换句话说:可重用。 我们不在乎如何创建Person对象,如果它是由工厂,另一个类创建的,或者它需要名称,年龄或任何其他依赖关系,我们只需要一个Person实例即可。 在软件工程中, 依赖项注入是一种技术,通过该技术,一个对象(或静态方法)可以提供另一个对象的依赖项。 依赖项是可以使用的对象(服务)。 注入是将依赖项传递给将使用它的依赖对象(客户端)。 让我们把这个例子转为日常问题。 在下面的代码中,我们的ViewController使用ListService对象。 这个ListService从Web服务加载数据,但是如果我们想从本地数据库,文件或其他地方加载数据怎么办? 我们需要创建另一个ViewController吗? 如果我们要测试此ViewController如何使API响应始终保持相同,以便可以验证测试? 现在考虑对此类进行测试,每次运行测试时,我们至少需要Internet连接和稳定的响应。 这使我们的测试变慢且不可行。 解决方案中使用依赖项注入来使用自定义的模拟ListService对象。 一种实现方法是创建一个具有load方法的接口,并在自定义对象中实现它。 换句话说,我们创建了Service协议和对象,它们知道如何从Web服务器,数据库,文件等中加载数据。 通过这种方法,我们可以轻松创建要使用的各种Service 。 例如,一个服务从Web服务加载数据,第二个服务从本地数据库加载数据,最后一个服务被模拟,因此我们可以使用它来测试ViewController而无需真正的API响应或本地数据库中的数据。 每种Service对象都可以具有唯一的依赖关系。 我们的WebServiceListService将需要知道如何发出请求,因此将需要一个Request对象。 DataBaseListService需要数据库连接才能加载数据。 这些独特的依赖关系对于我们的ViewController是不可见的。 它只需要一个具有load()方法的Service对象。 要测试我们的ViewController我们只需要创建一个MockListService并在测试期间将其注入即可。 注入对象使我们的代码解耦并且更易于测试。 这可以通过构造函数,setter或接口传递对象来实现。 附:如果您喜欢这篇文章,请在Twitter上分享,或在中级推荐,或两者都=)。 这确实有助于我吸引更多人。 非常感谢。

iOS中的测试驱动开发,SWIFT 4-第2部分

该博客是我在iOS上的“测试驱动开发”的第一个博客的延续。 请对此进行深入了解。 如果仍然如此,您会为此感到懒惰,那么您可以下载此博客UT_Starter2的入门项目并继续。 让我们回想一下我们正在建立的用于DemoTestsProject的UML图。 因此,让我们写下测试用例。 在进行单元测试时,我们应牢记的重要一件事是,我们应始终尝试测试我们的公共方法和属性,而避免测试私有方法和属性。 等待。 什么!!! 你是认真的家伙吗? 原因是公共方法和属性是我们向外界公开的内容,并且不希望它们出错。 关于此有一个很棒的堆栈对话。 请随时查看。 为了显示位置列表,我们使用表格视图。 因此,参考我们的UML图,我们有一个PlaceTableCell 代表对应于单元格的UITableViewCell类。 PlaceTableCell 使用PlaceCellDataModel的数据模型 键入以链接其UI。 因此,我们将测试数据模型是否正确设置了属性。 导航到PlaceCellDataModel.swift 并准备您的测试课程,如下所示: 让我们首先写下模拟DataFetcher。 导航到PlaceListViewModelTests 并将以下代码粘贴到类声明之外,除非您希望一个类位于另一个类中。 😉 祝贺您的模块成功进行单元测试。 编写业务逻辑测试用例。 模拟数据。 模拟数据获取层。 遵循TDD概念并构建代码。 示例代码:您可以在DemoTests Repo的Final文件夹中找到完成的项目。 您可以通过以下渠道与我联系,以获取任何查询,反馈或只是想进行讨论: Twitter — @G_ABHISEK 领英 堆栈溢出 邮件 abhisekbunty94@gmail.com 为了立即连接 SkypeId — gabhisekbunty 请随时与您的其他开发人员分享。

iOS Swift中的单元测试和TDD — pt1

单元测试是测试单个单元/组件的软件测试级别。 目的是通过测试组成程序的最小单元来测试程序的业务逻辑。 在面向对象中,这些最小单位是方法。 因此,我们通过提供输入来测试所有这些方法,并通过比较方法的输出并将其与我们的预期输出进行比较来测试逻辑。 简而言之,这是适合您的单元测试 。 减少错误。 改善设计。 允许重构。 降低变更成本。 好的文档。 简洁的代码示例胜于文档的许多段落 减少了程序员遇到的最大恐惧之一,那就是对一段代码进行更改,而不知道会破坏什么。 到目前为止,大家可能都在想。 如此多的讨论,让我们编写一些单元测试。 从此处下载启动项目。 这是一个简单的应用程序,它通过分别以米为单位的身高和以kg为单位的体重来计算一个人的BMI。 它包含一个名为BMICalculator的类,其中包含我们应用程序的业务逻辑,即用于计算一个人的BMI的逻辑,是的,您猜对了! 在本教程中,我们将测试该类。 运行项目,您将看到此屏幕。 玩应用程序,增加身高和体重,然后看一下您的BMI。 PS:请忽略应用程序的UI,因为我的设计技能不太好。 🙁 有两种方法可以在项目中添加单元测试。 1.从新项目开始 您可以在创建新项目时通过选中底部的“ 包括单元测试”复选框来添加单元测试 。 由于我们已经在项目中添加了单元测试,因此我们跳过此步骤。 2.在已经创建的项目中添加单元测试包 您也可以在已经创建的项目中添加单元测试。 转到文件>新建>目标 选择iOS单元测试套件 点击下一步 打开项目并转到底部的BMI CalculatorTests ,然后选择BMI_CalculatorTests.swift。 您会看到类似这样的内容。 当我们通过上述两种方法中的任何一种将单元测试添加到项目中时,这是Xcode创建的自定义单元测试文件。 让我们快速看一下单元测试的一些重要组成部分。 在最顶部,有一个导入,即导入XCTest。 XCTest库旨在提供一个通用框架,用于在Swift中为Swift软件包和应用程序编写单元测试。 在它下面,您将看到@testable import BMI_Calculator 。 这是Apple帮助您将应用程序代码导入到单元测试目标中的方式,以便您可以运行测试。 使用@testable时 ,无需将应用程序成员身份中的任何文件提供给测试目标。 Apple为您做到这一点,创建了一个很好的干净的分隔。 要创建单元测试,您必须继承XCTestCase 。 通过继承它,您将覆盖它的两种方法,即setup和teardown 。 正如其名称所表明的,它们用于在开始测试之前设置您的测试,并在完成测试之后将您的测试分解。 […]

选择移动架构的重要性

介绍 多年以来,移动应用程序的开发并没有在良好体系结构的设计上大放异彩。 可能是由于移动应用程序(主要针对有限的设备,例如PalmOS增强型设备或WindowsCE),并且由于这些设备的功能和程序如此有限,因此它们运行在很简单的地方,就像史蒂夫·乔布斯所称的“玩具应用程序”一样,需求很高,并专注于正确地构建应用程序架构。 那是用于银行系统或大型应用程序,而不是用于移动应用程序。 现在,情况发生了巨大变化。 我们希望从移动应用程序中获得比以往更多的方式:我们使用几次聊天,发送各种消息,共享和捕获图像和视频,还编辑音频和视频,所有这些都在“简单”的小手机中进行。 也许移动应用程序不是完全成熟的桌面应用程序(也不是必需的),但是它们现在能够执行许多有趣的事情,因此开发此应用程序已成为越来越复杂的任务。 几年前,我在一家大公司工作,在那里,我们开发的应用程序之一(最初是一个简单的POC)最终成为了实际产品。 设计完全是一团糟:没有对象或交互的感觉,没有界面,也没有设计或体系结构。 启动它的人甚至都不了解最基本的iOS编程知识。 当然,此应用程序非常容易出错,添加功能确实是一项艰巨的任务。 没有人想碰它。 “要使用最小化工作量并最大化生产率的设计和架构来构建系统,您需要知道系统架构的哪个属性可以达到这个目的” 所以..我们做了什么? 好吧,我们要做的第一件事是开始弄清楚应用程序必须做什么,并开始确定必须创建哪些组件,并开始考虑它们之间的交互。 最后,过程大致上是这样的:1)创建一个POC,以实际查看应用程序是否可以执行客户期望的操作2)找到更好的组织应用程序组件并创建出色设计的方法允许对该软件进行单元测试3)实现此设计。 一些有趣的设计模式: 很高兴为我们完成了许多此类工作。 反复发现相同问题的非常聪明的开发人员提出了几个“设计模式”的思想,它们基本上解决了我们可能遇到的一些问题,这是: 设计一个面向UI的应用程序,该应用程序可以具有相互交互的单独层。一种使更改变得简单并具有整套单元测试的好处的方法。 MVC:模型-视图-控制器 MVC是一个非常有趣的移动体系结构。 它是1970年代由Palo Alto Research开发的第一个MV *体系结构,迄今为止,它是许多移动开发平台和许多Web开发框架中的核心体系结构。 今天,Apple将这种体系结构用作其示例和所显示代码的主要体系结构。 这种架构的思想是将视图与控制器分离,将模型与控制器分离。 视图 :视图负责向用户呈现UI元素,以及用户输入和中间件之间的交互。 视图对象知道如何显示,并且可能允许用户编辑应用程序模型中的数据。 该视图不应负责存储其显示的数据。 (当然,这并不意味着视图从不实际存储其显示的数据。出于性能原因,视图可以缓存数据或执行类似的操作)。 ViewController :控制器对象充当应用程序的视图对象及其模型对象之间的中介。 控制器通常负责确保视图可以访问他们需要显示的模型对象,并充当视图了解模型更改的渠道。 控制器对象还可以为应用程序执行设置和协调任务,并管理其他对象的生命周期。 Model :这是应用程序用来表示数据并在ViewController和服务之间移动信息的抽象。 模型对象代表特殊的知识和专长。 它们保存应用程序的数据,并定义处理该数据的逻辑。 设计良好的MVC应用程序将其所有重要数据封装在模型对象中。 [1] MVP:模型视图演示者 该体系结构由Microsoft的Martin Fowler于1997年发明。 该模式基本上包括3个可互操作的层。 “ 模型 ”与MVC或MVVM中的概念相同。 然后,“ Presenter ”是Model与ViewController或View Controllers与服务之间的中间层。 这是我们将要测试的层。 […]

使用Apollo和GraphQL在Swift中进行单元测试的指南第一部分

作为iOS开发人员,我们通常依靠URLSession来为我们的网络层编写单元测试。 鉴于GraphQL和Apollo抽象了我们的网络层并充当了网络资源的黑匣子,我们不能依靠典型的URLSession模拟策略来实现最大的单元测试覆盖率。 让我们使用一个公共的GraphQL API创建一个示例应用程序并编写一些单元测试。 我们的示例应用程序将是一个简单的表格视图主详细信息应用程序,该应用程序列出了仓库的国家/地区,并可以在详细信息页面上加载有关它们的详细信息。 首先,让我们考虑一下如何构造数据。 考虑到母版页仅需要一个国家的几个数据点,而详细信息页将需要更多有关特定国家的数据。 这是使用GraphQL的原因之一,我们实际上可以为单独的用例定义单独的模型。 这种仅获取给定屏幕所需内容的技术可以为我们的应用程序提供性能改进,减少我们的TTI(交互时间)并改善用户体验。 我们将定义一些GraphQL片段来设计模型。 在Swift结构中定义数据模型后,我们应该为这些对象从GraphQL模型中创建可选的初始化器。 这实际上将使解析我们的数据并将其转换为我们服务中的域模型变得简单。 Apollo将所有内容都设为可选everything,因此我们所有的初始化程序都将失败。 您可能知道从GraphQL数据中删除可选性的更好方法,如果需要,请发表评论。 在进行转换以处理可选性时,我们将依靠flatMap和compactMap 。 最初发布在 gist.github.com上 。

iOS应用中的单元测试与模拟

您刚刚开始一个项目。 按照典型的方式,不同的人处于不同的阶段。 在早期阶段,只有您和设计师。 但是随着项目的开展,他们开始引入Web api开发人员来构建Web服务,您最终将将其连接到应用程序的用户界面。 这产生了一个难题,许多开发人员都在以不同程度的成功来解决这个难题。 如何在不依赖Web服务的情况下构建应用程序及其用户界面? 这样的事情有可能甚至被推荐吗? 那是单元测试的目的吗? 人们兜售一个叫做“测试驱动开发”的东西会说“是”。 他们认为您要先编写测试,然后再编写通过测试的生产代码。 在童话般的土地上,人们显然有时间这样做,这一切都很好,但是给我们大多数人大约一两个月的时间,为我们的客户建造某种可释放的东西。 编写单元测试作为在所有人入职之前验证所有功能(包括用户界面外观)的一种方式,是不现实的。 嘲弄是工作的正确工具。 模拟是伪造的实体,模型或服务。 处于早期阶段的应用应具有各种模拟。 您可以拥有假用户,假事件,假场所,假网络服务。 一切都应该是假的。 但是,尽管您的模型和服务是伪造的,但是您的视图,视图控制器和其他应用程序逻辑确实可以是非常真实的。 那就是嘲笑某件事的全部重点。 就像压出面包模一样。 您可以使用一块木头来使形状正确,但是您完全打算在烘烤时在其中放入真实的面团。 您可以使用伪造的模型和服务启动应用程序项目,在不同的ViewController之间传递它们,并扩展应用程序的大多数用户交互。 稍后,一旦将Web开发人员加入团队,您就可以慢慢开始用真实的交易替换假模型和服务。 如果您一直在使用诸如Model View Controller和Model View View-Model之类的设计模式,则将模拟与真实实体交换应该是一件简单的任务。 在大多数情况下,只需更改类名或添加带有JSON的初始化程序即可。 一个好的模拟尽可能地接近真实交易。 因此,如果您的应用程序具有一个具有名字,姓氏,电子邮件地址和个人资料图片的用户实体,则模拟用户应具有所有相同的属性。 实际上,您的模拟模型可能与最终模型完全相同。 这就是您所追求的。 您希望一旦有可用数据就可以用真实数据填充。 我已经看到在不同的iOS团队中以多种方式完成了模拟。 不太先进的团队从来没有完全内部化模型-视图-控制器,MVVM或关注点分离的概念。 他们创建了松散组织的不同数据阵列,完全希望稍后再回来并重做所有工作。 结果,他们的模拟看起来像这样 您可以看到对应用程序架构的思考很少。 他们只是将一些数据放入数组中,并假设他们在Web服务可用之前无法开始构建应用程序。 但这不是真的! 即使您的数据不是真实的,您也可以创建结构。 更高级的团队将把他们的模拟视为他们计划长期使用的真实模型。 它们将在ViewController之间传递它们,就像传递真实交易一样。 结果,一个伟大的团队的模拟将看起来像这样 是否需要该协议还有待商bat。 我将其放在此处以强调“ 人”是适用于假人和真实人的抽象概念。 要将伪造与真实交换,您仅需要创建一个符合Person协议的新实体。 区别是显而易见的。 经验更丰富的团队创建了一个久经考验的真实架构。 经验不足的团队创建了一系列无关的东西。 高级团队可以在应用程序周围传递模拟,就像它们是真实的一样。 他们可以完成90%的工作,而无需将任何事情挂接到实际的Web服务上。 […]

单元测试

单元测试提供了一段代码必须满足的严格的书面合同。 结果,它提供了几个好处。 单元测试会在开发周期的早期发现问题。 理想情况下,每个测试用例都相互独立。 单元测试通常由软件开发人员编写和运行,以确保代码符合其设计并按预期运行。 单元测试的好处 使流程敏捷 当您敏捷开发产品时,更改是您需要牢记的最重要的事情之一。 当您的应用程序功能不断增长时,更改已经测试的代码非常危险且成本很高。 但是,如果我们在正确的位置进行了测试,则可以放心地进行重构。 单元测试确实与各种口味的敏捷编程紧密结合,因为它内置测试,使您可以更轻松地进行更改。 换句话说,单元测试有助于安全重构。 2.代码质量 单元测试可以提高代码的质量。 它确定在进一步发送代码进行集成测试之前可能出现的每个缺陷。 在实际编码之前编写测试会使您对问题的思考更加艰辛。 它暴露了极端情况,使您可以编写更好的代码。 3.尽早发现软件错误 由于单元测试由在集成之前测试单个代码的开发人员执行,因此可以很早地发现问题,然后就可以解决问题,而不会影响其他代码。 4.促进变更并简化集成 单元测试允许程序员在以后重构代码或升级系统库,并确保该模块仍然正常工作。 单元测试检测可能会违反设计合同的更改。 它们有助于维护和更改代码。 单元测试可减少新开发功能的缺陷或减少更改现有功能时的错误。 5.提供文件 单元测试提供了应用程序的实时文档。 希望了解特定单元提供什么功能的开发人员可以参考单元测试以了解该单元的应用程序编程接口(API)。 API根据输入,输出和基础类型指定组件。 6.调试过程 单元测试有助于简化调试过程。 如果测试失败,则仅需要调试代码中最新的更改。 7.降低成本 试想一下,在开发的后期阶段(例如在系统测试或验收测试期间)发现错误的代价。 当然,较早发现的错误更容易修复,因为较晚发现的错误通常是许多更改的结果,并且您真的不知道是哪个原因导致了该错误。

如何在Swift中编写单元测试而不公开所有内容。

每当我参加讨论单元测试主题的会议演讲时,我都会听到两个问题。 1.我如何说服老板给我时间写这些书? (您没有。您只需编写它们。)和2.单元测试破坏了封装。 你是在告诉我我应该公开一切吗? 我在iOS / Swift的世界中工作,那里有解决特定问题的工具,但总体感觉是,我们必须破解向团队其他成员开放的所有功能,才能进入那里并测试一些变量当他们应该被设置时就被设置。 因此,在进一步详细介绍之前,请先进行警告。 本文的目的是激发话题,而不是倡导任何特定观点。 您采用的任何方法都有其优点和缺点,并且在继续进行计划之前,获取尽可能多的信息总是明智的。 自动化测试虽然不错,但是永远不会修复架构不良的应用程序。 我也不声称他们曾经做到过。 从坚实的基础开始建设总是比将绷带应用于需要推倒的东西总是更好。 ew 感觉很好。 好的,有点自以为是! 这到底是什么问题? 当我们在团队中工作时,每个开发人员都定义了一个API,团队中的其他成员在使用他们的代码时都可以访问。 重要的是,我们要给我们的团队成员一些容易理解的东西,否则他们可能会对我们的代码感到困惑。 如果一个类具有太多面向公众的功能,而另一个开发人员需要相当频繁地使用它,则可能会造成混乱。 与创建具有太多菜单选项的应用程序没什么不同。 用户不容易确定哪个选项是正确的选择。 但是实际上,这比那更糟。 其中一些选项可能会对应用程序致命。 有些变量和函数不应该在类之外使用,因为这样做可能会引入意外的行为。 这就是为什么我们每个人都决定为我们的同伴程序员定义一个api。 我们说“这是公共的,您其他开发人员可以在不破坏应用程序的情况下使用它”,“这是私有的。 没有人可以触摸它。” 这是很长时间以来的样子,并且确实运行良好。 这是传达意图的明确方法。 单元测试与私有方法 不幸的是,这种方法不适用于单元测试。 原因很简单。 在iOS中,您不能针对声明为私有的任何内容编写测试。 等等什么 您应该如何进入那里并测试所有内容? 您应该测试所有内容吗? 您应该只测试几件事吗? 你应该测试什么? 你不应该测试什么? 这变得令人困惑。 似乎没有关于它的手册,而且不同小组之间来回往来很多。 有素食主义者说,单元测试就像在吃蔬菜一样,看着自己变得不健康。 然后是另一个团队放弃了,因为似乎需要考虑太多,而他们的老板也不允许他们编写测试。 我被困在这里问,又是什么问题? 它必须是如此二进制吗? 在这里,我主张“仅仅公开一切”并不是一件坏事。因此,在这里,你也让我死死盯着我的建议的荒谬之处。 好的,那部分结束了。 不管你怎么想,我确实有一个问题。 您是否认为公共/私有的重要性取决于其他外部因素,例如团队规模,项目复杂性,代码可重用性等? 当然,BigCo的一个应用程序项目需要数百名团队成员研究相同的代码,而SmallCo的项目可能只有一两个人正在查看相同的代码。 它必须是。 在较大的公司中,不同人群之间的交流要少得多。 由于无法快速召集您讨论如何与您的班级一起工作,因此定义什么是私有的和什么不是私有的更为重要。 但是,在较小的公司中,只要有一点混乱,您就可以与该人配对。 […]

构建iOS单元测试的四个简单规则

您已经知道什么是单元测试,并且您可能已经在自己的iOS应用中编写了其中的一些测试。 那很棒! 现在,我们将进一步了解单元测试的结构。 当以某种方式编写单元测试时,它们是最有效的。 目标是以一种有组织的方式隔离组件和行为,从而使您深入了解应用程序的哪些部分有效,哪些无效。 只需一点技巧,您就可以编写单元测试来帮助您诊断问题,从而节省了比花费更多的时间。 这是创建测试套件时应遵循的最佳实践的简单列表。 隔离组件 好的单元测试不会尝试一次全部测试。 它一次测试一个组件的一种行为。 这是一个简单的经验法则。 每个要测试的组件都应该有一个XCTestCase文件。 该组件的所有测试都在该文件中。 在我的一个项目中,我有一个类来验证用户在文本字段中键入的薪资。 我将其称为PayrateValidator ,并将其命名为PayrateValidator.swift 。 在相应的测试套件中,测试PayrateValidator的XCTestCase子类称为PayrateValidatorTests ,包含该文件的文件称为PayrateValidatorTests.swift 。 这样一来,您也可以轻松地发现应用程序的哪些部分未被单元测试覆盖。 如果没有相应的测试用例文件,则很有可能没有该组件的单元测试 。 您还可以使用Xcode的测试覆盖率工具,我们将在另一篇文章中进行介绍。 关键是要有某种命名约定,以便您知道哪些文件可以测试什么。 等待。 我没有像这样的小组件。 我该怎么办? 对于初学者的iOS开发人员而言,这可能很难。 如果您没有MVC或MVVM等设计模式的经验,则您的应用程序可能没有任何隔离的组件。 您可能拥有一个巨型视图控制器,其中包含所有应用程序功能。 没办法判断。 我们都必须从某个地方开始。 我自己写了很多庞大的视图控制器。 编写好的单元测试的关键是要理解,您需要将应用程序分解成可以测试的较小部分 。 例如,如果视图控制器进行网络连接,请提取该逻辑并创建一个可以测试的单独的网络服务组件。 如果您不知道从哪里开始,请继续阅读一些常见的iOS应用程序设计模式,例如MVC或MVVM。 只需遵循这些步骤,您就会自动获得一个具有单独组件的应用程序,与庞大的视图控制器相比,这些组件更容易进行单元测试。 隔离行为 假设您已经隔离了一个组件。 您有一个与其关联的XCTestCase文件。 凉! 现在您需要测试。 结构良好的单元测试套件将每个组件分解为行为,每个行为都有其自己的功能来测试它们。 假设您正在编写Rick Astley的人工智能版本。 只是奠定基础,您可以像这样模拟他的一些行为。 这必须是Rick Astley的最笨拙的AI版本,但是也许这是您永远需要的所有编程。 在您的测试用例中, 通用约定是在单独的函数中测试不同的行为 。 它应如下所示。 在这里,我们只是断言,Rick […]

快速咬合#1:测试Swift可选

快速测试可选组件时 ,有两种方法。 其中之一是通过在我们的代码中引入条件(如果,守卫……),但这是我们在测试中要避免的事情,因为添加新的流程并不是我们测试所希望的。 我们如何避免这种情况? 我们可以使测试失败,从而中断测试,但又不中断其他测试的执行,同时避免在代码中添加条件。 这是可恢复和不可恢复错误起作用的地方。 就本文而言,我们仅关注可恢复的错误。 崩溃 避免在我们的代码中引入条件的一种方法是让测试崩溃。 当测试崩溃时,Xcode将恢复并恢复未决测试的执行。 您可以通过强制展开可选内容来完成此操作,如果该值为nil,则测试将崩溃。 测试将恢复,但是Xcode将出现以下错误: 就个人而言,我宁愿避免重新启动Xcode来恢复测试,而这就是下一个选择的地方: 扔 测试失败的另一种方法是让它抛出错误。 但是众所周知,展开时不会抛出可选选项 。 但这可以通过在Optional枚举中添加新功能来轻松解决。 我们只需要添加一个在包装值的解压缩为nil时引发错误的函数。 我们可以这样做如下: 您可以阅读的第一件事是在发生展开错误时我们希望打印的消息,以在调试器中获得更多帮助。 第二部分是调试器为测试失败打印的内容。 显然,与坠机事件相比,该消息没有那么生动。 那么,您应该选择哪一个呢? —完全取决于您。 我的建议是选择崩溃而不是崩溃,因为它不需要Xcode来恢复那么多。 对我来说,每次在Xcode而不是终端上运行时测试崩溃时,Xcode都不会继续执行其余的测试文件,但是当测试抛出错误时,Xcode会继续运行。 有关可恢复和不可恢复错误的更多信息,请阅读John Sundell的精彩文章。 Swift Bite是一系列小的“直截了​​当”的文章。 我希望以后继续谈论更多可以简单解释的不同事情。 如果您喜欢这篇文章,请考虑拍一下。 另外,如果您愿意,可以在Twitter上关注我,@ MikePT28或“中”。