Tag: 测试

使用SwiftyMocky生成模拟并简化Swift中的单元测试

简单的5点指导可将您的单元测试带入一个全新的水平。 总体来说,Swift世界最近发生了很多事情,这种趋势并没有错过对开发的一部分进行测试的机会。 尽管良好的测试实践正在传播,但对旨在帮助该过程的工具的需求也在增长。 我很高兴成为一个团队的成员之一,该团队致力于开发一种名为SwiftyMocky的解决方案。 1.模拟是测试双 一般而言,在谈论单元测试和测试时,有一整套特殊目的的对象,称为“测试双打”。 在本文中,我将仅简要介绍它们,因为需要理解SwiftyMocky背后的整个概念。 Test Doubles背后的故事很简单。 由于缺乏更好的词汇,经典的测试方法通常依赖于状态验证。 我们为sut及其依赖项创建初始状态,然后验证执行测试后的状态是否符合我们的期望。 尽管如此,并不是在每个测试用例中我们都在测试sut ,我们可以使用实际的实现作为其依赖项。 数据库操作或网络调用就是一个很好的例子。 我们真的不想在这里进行真正的通话,因此sut尝试进行的了解通常足以确保有效性。 另一个很好的例子(来自Martin Fowler的帖子)是发送电子邮件-很难从测试角度进行验证。 这就是我们的特殊情况对象出现的地方。 基于Gerard Meszaros提出的词汇(我个人觉得非常有用),我将其分为以下几类: 虚拟 :完全没有实现,该对象的整体唯一目的是满足依赖关系要求。 伪造的 :简单但有效的实现,通常采用捷径。 例如,伪存储将宁愿使用某些内存数据结构(如数组或字典),而不是包装核心数据操作。 在提供与具体实现相同的功能的同时,它使状态验证更加容易。 存根 :包含预定义的响应和答案,通常严格针对特定测试用例定义。 Spy :存根,不仅返回预定义的答案,还记录调用的方法。 模拟 :预先设定的期望值,可以验证sut的行为是否符合预期。 在本文的其余部分,我们将重点介绍Mock ,因为它可以处理正确测试所需的大多数内容。 请注意,虽然上述单词在测试双精度类型之间严格区分,但是在大多数工具中, Mock 都是扩展的,具有 Stub 和 Spy的 组合功能 。 在 SwiftyMocky中, 我们执行相同的操作,因此,每当引用 Mock时 ,我们的意思是同时提供 Stub 和 Spy 功能的对象。 尽管拥有Mock对象的想法很明确,并且收益不能被夸大,但这给我们带来了一个问题。 必须编写模拟实现,如果有适当的层分离,则在大型项目中这可能会成为相当大的开销。 在具有适当反映的语言中,有许多库和框架可以在运行时创建Mock ,使您可以选择一种最适合您的测试风格的库。 […]

如何使用FBSnapshotTestCase在iOS中进行UI测试

在视图控制器中更改某些代码已经发生了多少次,并且在生产环境中测试应用程序时,视图已经发生了神奇的变化? 如果我们不想,我们是否应该有某种方法来确保视图不变? 因此,进行UI测试很重要。 通过添加UI测试,我们可以确保不会对UI进行意外更改。 在本文中,我们将在一个简单的示例项目中专注于FBSnapshotTestCase的用法。 FBSnapshotTestCase的历史 最初,FBSnapshotTestCase由Facebook创建和维护。 这是一个非常有用的工具,具有非常简单的实现。 所需要做的就是将库集成到项目中,并实例化我们要测试的UIView或UIViewController子类。 不幸的是,自去年以来,Facebook已停止维护该工具。 Facebook已经创建了另一个与其内部基础设施紧密相关的工具,因此他们不赞成该工具。 对我们来说幸运的是, Uber决定为他们当前维护的项目创建一个分支。 FBSnapshotTestCase测试实际上是单元测试,它使我们能够将UIViewController的参考图像(也可以是UIView,但通常是在全屏模式下)与视图的当前呈现进行比较。 如果存在任何不一致(第一张图像与第二张图像之间存在差异),FBSnapshotTestCase将生成第三张图像,并以灰度标出差异。 如果参考图像和项目中的电流之间存在差异,则该工具将生成此第三张图像,并且在该单元测试中会生成错误,从而导致测试套件产生故障。 Fastlane为我们提供了类似的工具Fastlane Snapshot(存储库),它使我们能够在Xcode UI测试中截取屏幕截图。 所有UI测试完成后,如果它们都获得批准,它将生成带有所有屏幕截图的HTML文件。 Fastlane Snapshot默认情况下还允许我们设置我们要查看的所有设备和语言。 这对于测试所有可能的组合非常有用(如果您有3种语言,应用程序中有10个屏幕,并且支持5种设备,则它会生成3 x 10 x 5 = 150个屏幕截图!)。 问题在于,这只是一个屏幕截图,它没有为我们带来有关图像是否具有正确UI的信息。 总而言之,FBSnapshotTestCase允许我们比较并告诉我们是否有任何错误,Fastlane Snapshot只是为我们带来了Xcode UI测试的屏幕截图。 我们将讨论以下主题,力图充分利用该工具的潜力: 如何集成FBSnapshotTestCase 使用SnapKit重构代码并使用FBSnapshotTestCase 编写脚本以生成具有不同分辨率的屏幕 要开始本教程,请下载以下示例项目https://github.com/fedejordan/FBSnapshotTestCaseExample 在模拟器中编译项目(我使用过iPhone 8),您将看到以下屏幕: 一个简单的View Controller,可以是任何应用程序的第一个屏幕,带有登录和注册按钮。 我已经使用CocoaPods集成了SDK。 您可以使用Carthage或您选择的包裹管理员。 集成该工具的步骤在存储库指南中。 为了方便起见,以下是使用CocoaPods的安装说明: 在终端应用程序中,我们输入pod init以创建podfile 在podfile中,我们添加pod ‘FBSnapshotTestCase’ 我们在终端中进行pod install以下载SDK 我在这里使用的版本是2.1.6 将SDK集成到项目中后,我们将打开CocoaPods生成的工作区并编译项目,以确保一切正常。 就像它在FBSnapshotTestCase官方指南中所说的那样,我们转到Edit […]

iOS测试技巧#2-提高测试代码的可读性

这是我撰写有关测试的提示的系列文章的第二篇,您可以在此处查看另一篇文章: iOS测试技巧#1-跟踪辅助功能测试失败 软件开发中最有害的事情之一是无法读取的代码。 当我们失去太多精力去理解某些代码时,我们会花费更少的精力来查看极端情况,这是产生错误的最有利条件之一。 测试是消除bug的武器,因此它很重要,但是如何知道它有效呢? 不要看代码覆盖率就知道是否正在测试某些东西,因为代码覆盖率只会检查这些行是否已执行。 即使没有灵丹妙药,您的测试代码也越不可读,要找出是否正在测试所有必要的上下文就越困难。 有一些技术可以帮助您组织测试代码,使其更具可读性。 在这篇文章中,我将以一个简单的测试服开始,然后将通过应用这些技术来前进。 在此示例中,只需尝试找出正在测试的内容以及如何使用它。 。 在上面的示例中,我们很难发现要测试的内容,而Arrange-Act-Assert可以帮助您解决这一问题。 该技术可帮助您从设置和断言中分离出正在测试的内容。 使用这种技术,可以更清楚地知道是否存在同时测试多个对象的测试方法。 这项技术可以帮助我们确定自己正在测试的班级,我个人并没有使用太多。 设置方法在测试套件的每个测试方法之前运行。 此步骤很重要,但要明智地使用,您的测试应该易读且易于维护,过度使用设置方法可能有害,因此您必须评估最适合自己的方法。 比较每个重构步骤,并了解哪种方法更适合您的环境。 所有人,谢谢您的阅读!

带有TDD的手工iOS应用程序中的身份验证规则

让我们从身份验证过程开始,但并非全部开始,目前,我们仅对注册部分感兴趣。 这部分具有一些验证和重要行为。 此实现将使我们能够与一些BASS内容进行交互,这代表了应用程序难题的重要组成部分。 在这篇文章中,我们将介绍: 测试驱动开发 输入数据验证 准备与外部服务的一些集成 您可以在此处检查相关的github问题。 用户注册用例 该项目将使用自下而上的流程进行开发。 因此,我们将从编写测试和规则开始,而不是进行注册或登录屏幕。 第一个测试即将尝试使用空电子邮件值注册用户。 经过绿色测试之后,该重构用例类了。 第一个奇怪的是寄存器功能处的mutating关键字。 需要使用此关键字是因为该函数试图更改默认情况下不可变的结构值。 此应用程序将使用称为Clean Architecture的体系结构,该体系结构将软件分层。 这些层对于隔离按行为分开的组件和职责至关重要。 清洁体系结构和SOLID原则值得一提,我将在稍后单独讨论。 通过将软件划分为多个层,并遵循“依赖关系规则”,您将创建一个具有内在可测试性的系统,并具有其所隐含的所有优势。 马丁,罗伯特。 “清洁建筑” 2012 同样,此用例正在保存应该在表示层中的状态。 不在“应用程序业务规则”层中。 为了解决这个问题,我们可以创建一个演示者。 …我们也不希望该层受到数据库,UI或任何常用框架等外部性变化的影响。 该层与此类问题无关。 马丁,罗伯特。 “清洁建筑” 2012 上面的协议将成为演示者。 而且它的实现与用例无关紧要。 用例只需要具有故障方法的东西。 在我们的测试环境中,我们将使用演示者的测试双精度表示形式,该表示形式为存根双精度类型。 出于测试目的,我们可以用等效的“特技替身”: Test Double来代替真实的DOC(而不是SUT!)。 迈扎罗斯(Meszaros),杰拉德(Gerard)。 2009年“ Test Double” 存根提供对测试过程中进行的呼叫的固定答复,通常通常根本不响应为测试编程的内容。 存根还可以记录有关呼叫的信息,例如,电子邮件网关存根可以记住“已发送”的消息,或者仅记住“已发送”的消息数量。 福勒,马丁。 “不打Mo”,2007年 用例已更改为通过依赖关系使用演示者。 演示者将用作用例的依赖项,这样做将符合SOLID原则,更具体地讲是Dependency Inversion一个。 原则指出: 答:高级模块不应依赖于低级模块。 两者都应依赖抽象。 B.抽象不应依赖细节。 细节应取决于抽象。 马丁,罗伯特。 […]

使用AcceptanceMark自动生成Xcode测试

自动生成测试? 是的,请。 这篇文章展示了如何使用Markdown表为您的软件/应用程序编写业务逻辑 ,以及如何使用名为AcceptanceMark的命令行工具为Xcode 自动生成测试 。 但是首先,一些背景 。 您的代码可能具有以下测试形式: 单元测试 整合测试 验收测试 UI测试 阅读此处 可以很好地了解它们之间的区别。 此外,您可能有一个专门的质量检查小组,并定期手动运行您的应用程序以验证其正确性。 虽然编写好的测试对于构建高质量的软件是必不可少的,但这也需要花费很多时间。 我将向您展示如何更快地测试代码 ,以便您可以将时间花在更重要的事情上! 测试,Xcode方式 在Xcode中,可以通过子类XCTestCase编写单元测试或UI测试 。 假设您的被测系统(SUT)是一种日期格式化程序,需要使用各种可能的语言/输入日期才能正常工作。 测试类可能如下所示: 并将其自动转换为Xcode测试类吗? 好吧, 我已经编写了一个名为AcceptanceMark的工具来 完成该任务 。 只需在终端上运行此命令: amtool -i DateFormattingSimple.md 该工具将生成如下所示的Swift测试文件: 一些观察: 年 , 月 , 日 , 小时 , 分钟 , 第二列被注释为Int 。 AcceptanceMark还不支持将日期作为内置类型使用,但是可以在此处使用单独的组件,以便日期输入与格式无关。 语言列是语言环境标识符字符串。 dateStyle列是一个字符串。 dateStyle和localizedDate之间有一个空列。 这称为分隔符列 。 AcceptanceMark将其前面的所有列均视为输入,并将其之后的所有列均视为输出。 AcceptanceMark始终需要分隔符列 […]

测试苹果MVC

苹果公司针对iOS应用程序的官方主要设计模式是模型视图控制器。 该模式包含一个模型(包含我们的数据),一个视图(显示数据)和一个控制器(将所有内容粘合在一起)。 从他们的角度来看,一切都可以归为这三个组成部分之一。 因此,让我们看看如何测试每个组件。 模型 该模型包含工作所需的数据。 不过要小心; 它不包含仅与视图相关的任何数据,例如按钮显示的文本。 相反,它可能是核心数据存储或游戏系统。 这意味着我们已经知道如何测试模型。 模型公开了一个api(方法,属性等),并且不需要任何额外的工作来设置测试。 视图 对于视图,我们必须假设Apple负责将物理交互转换为数据并将其传输到屏幕/视图的正确位置。 有了这个假设,我们可以创建我们要测试的两种视图数据: 静态的 更换零件 我们可以通过创建屏幕快照来测试静态部件,然后将当前屏幕快照与此进行比较,但老实说,这对于UX来说是有用的。 作为开发人员,我认为只要专注于视图的不断变化的部分和交互作用就可以了。 有趣的是,这导致我们必须测试控制器,因为它正在传达交互作用。 控制者 让我们开始研究应用程序的功能。 在iOS中,它称为ViewController。 该控制器接受事件,控制逻辑并使我们的应用程序正常工作。 所有这些功能都留下了“难以测试”的印象。 至少它对我有用。 如果您认为iOS具有两种不同类型的InterfaceBuilder创建视图,它将变得更加强大。 那么为什么它似乎很难测试? 它做的很多,这意味着要进行大量的测试和进行交互的各个部分。 如何测试视图生命周期的方法? 特定于视图的方法,例如tableView(tableView:didSelectRowAt 🙂 如何测试IBAction? 如何测试IBOutlets? 让我们解决所有这些问题。 它做很多 听起来很糟糕,确实如此。 在大多数情况下,您需要考虑重构代码。 如果您无法减少代码中的功能量,它仍然不会阻止您进行测试。 一开始只是令人恐惧,您可能想在此过程中进行重构。 如何测试视图生命周期的方法? 有两种意见。 一种是您以与其他所有操作相同的方式来称呼它们。 只要您没有引用IBOutlets的代码,您甚至都可以自己经历整个生命周期。 另一个选择是从这些函数中提取所有代码,然后调用它们。 这样,您始终可以确保小型逻辑代码片段能够按预期的方式运行。 因此,这与我们在其他地方所做的相同。 特定于视图的方法 听起来很奇怪,但最终它们只是功能。 在这种情况下,它们是公共的,因此您不必创建类别并添加它们。 IB动作和IBOutlets IBActions只是方法。 给他们打电话! 另一方面,IBOutlets需要ViewController来扩大视图并设置所有Outlets。 一旦完成,就可以使用与属性相同的方式进行测试。 所以问题是:如何为视图充气? […]

与Jenkins和Fastlane的持续集成和持续交付

测试一直是大多数大中型项目的重要组成部分,因此,对我们的主分支进行的每次代码更改都必须触发测试套件的完全执行,这一点很重要,以确保我们所做的更改不会破坏其他任何代码测试用例。 这就是我们所说的持续集成(CI)。 这是为了验证代码更改的正确性并快速识别集成错误。 在收到CI的同意后,下一步是确保交付包含新功能和/或错误修复的新软件。 这就是我们所谓的持续交付。 由于CI已解决了测试套件的问题,因此我们在此处运行脚本以对证书进行签名(在Xcode / iOS上下文中),并使用第三方工具(如FastLane)执行存档,以触发可发送到用户电子邮件的可部署软件。立即进行测试。 詹金斯是什么? 詹金斯(Jenkins)为我们提供了无缝方式,以使用管道为几乎任何组合的代码语言和源代码存储库设置CI / CD环境。 它是一个开源自动化服务器 ,可用于自动化与构建,测试以及交付或部署软件有关的任务。 它也是帮助DevOps团队的必不可少的工具,由于我们在特定时期内管理的项目数量不断增加,以确保其高质量的交付成果, DevOps团队如今越来越受欢迎。 Jenkins的插件可与Github和BitBucket等第三方源控制器集成。 什么是Fastlane? FastLane是用Ruby编写的CD工具,用于发布移动应用程序(iOS / Android),为您消除了繁琐的任务。 由于其针对iOS生态系统的较早开发,我们可以看到iOS提供了比Android更多的功能。 注意:如果您是Fastlance的新手,也可以查看我们的Fastlane教程 。 先决条件 为了完成本教程,我假设您已具备以下知识和工具: 有关构建iOS项目的一些基本知识。 Swift中一些具有Quick&Nimble的单元测试知识。 一些虚拟主机知识。 使用本教程的Mac机器。 用于生成证书的开发者帐户。 忍耐 设置整个过程非常耗时且乏味。 通过大量的试验和错误,我可以将所有内容拼凑在一起,以创建本教程。 在撰写本文时,可能会有更新进入,内容可能已过时。 请比较出现的版本升级并进行相应处理。 不要犹豫,给我留言,这样我就可以相信您并更新本教程,以使其余人员受益! 谢谢☺ 你会学到什么? 通过阅读本教程,您将学到很多有关CD和CI的知识,包括: 如何设置Jenkins 2.121.3(Java 8) 。 如何设置Fastlane 。 如何使用Jenkins + Github管理您的CI 。 如何使用Jenkins + Github + Fastlane管理CD […]

破解核心数据测试

核心数据是一个框架,它隐藏诸如对象生命周期和对象图管理之类的持久层的逻辑,以帮助您以高级方式管理模型层对象。 是的,Core Data对许多开发人员来说都是有争议的。 但是,它仍然是有用的框架:性能良好,并且得到Apple的支持。 关于核心数据的单元测试,有很多不错的文章,但是大多数文章集中在模拟上下文。 由于发布了持久性容器类NSPersistentContainer,因此越来越难以模拟上下文并将测试写入容器。 因此,在本文中,我将探讨一个新主题:为NSPersistentContainer编写测试,增强型核心数据。 我们将一起使用NSPersistentContainer设置核心数据堆栈,并为此编写测试。 TL; DR 我们将学习如何: 使用NSPersistentContainer构建核心数据栈 使用内存永久存储 引入两个测试双打:“假”和“存根” 做一个异步测试 先决条件 迅捷3 Xcode 8 核心数据基础知识 iOS 10(由于我们将使用NSPersistentContainer,因此需要iOS 10)。 以下是一些有关核心数据的好文章: 完整的核心数据应用程序(代码在Objective-C中,但是概念相同) 核心数据入门教程 我们的任务 现在,我们有一个简单的任务:实现待办事项列表系统,在其中我们可以创建,读取,更新和删除待办事项(CRUD)。 而且这个待办事项系统应该永久保存数据,以便即使我们终止应用程序也可以稍后获取它们。 因此,我们需要实现这些方法: 创建待办事项 提取所有待办事项 删除待办事项 提交对永久存储的更改 由于我们只想在需要时执行保存,因此我们不会在创建/编辑/删除方法中将NSManagedObjectContext .save()视为副作用。 相反,我们将其设为独立方法。 当用户按下“保存”时将允许保存数据,或者当用户离开当前视图时将其保存。 尽管通过使用NSPersistentContainer在iOS 10之后设置Core Data堆栈更容易,但最好具有一些基本知识。 我们将在以下各节中采用这些概念。 因此,在下一节中,我将简要介绍Core Data堆栈。 核心数据栈 根据苹果公司的说法,核心数据栈是框架对象的集合,这些对象是核心数据初始化过程的一部分。 核心数据堆栈中包含4个基本组件: 托管对象上下文 (NSManagedObjectContext):为托管对象提供便签本 持久性商店协调器 (NSPersistentStoreCoordinator):汇总所有商店 托管对象模型 (NSManagedObjectModel):描述商店中的实体 持久对象存储 :包含已保存的记录。 […]

测试仪或方案接口BDD和体系结构MVVM

在应用程序界面上倒入测试仪,在界面上进行测试时应遵循的原则,或者在最佳方式下可以使用此方法。 检验界面的刚度,强度和脆弱性 。 借用:解决方案选择的技巧,未经测试的临时执行子接口。 Ils nesont pas force与工业化完全兼容(例如:une executiondéclenchéeau commit)。 德,法执业者和劳力士。 僵化 : 更改设备的测试界面,维护时间不长。 脆弱 :经验丰富,执行力十足,而詹姆斯·加兰蒂则无能为力。 最好的解决方案,最好的方法是合理的使用。 识别和测试双重接口的界面(KeyFeature) 。 Ces parcourscléssont la raison d’êtrede votre应用程序。 倒入商业应用程序:测试或测试面板。 在界面上倒入测试器,并在其他可信任的地方使用BDD( 行为驱动开发 )。 一流的测试人员和界面的测试人员 ,快速和强大的测试人员,可以很好地融合各种测试方法 ,以方便地定位和应用这种界面。 联盟架构MVVM ,最简便的BDD接口测试仪。 Un BDD peut tester la dynamique UI: d’un change de de couleur ou d’image 禁忌的立场 d’un segue ou de l’apparition d’un弹出窗口 […]

在iOS中测试viewDidLoad

假设我们有以下视图控制器 类ListController:UIViewController { 覆盖func viewDidLoad(){ super.viewDidLoad() view.backgroundColor = .white } } 了解viewDidLoad 我们知道第一次创建viewDidLoad会调用viewDidLoad 。 因此,在单元测试中,如果使用viewDidLoad进行触发,则会陷入陷阱 func testSetup(){ 让控制器= ListController() controller.viewDidLoad() } 为什么viewDidLoad被调用两次? 在测试中被调用一次 在您的viewDidLoad方法中,您将访问第一次创建的view ,因此它将再次触发viewDidLoad 正确的方法 最佳做法不是自己触发事件,而是做一些事情使事件发生。 在单元测试中,我们只是访问view以触​​发viewDidLoad func testSetup(){ 让控制器= ListController() 让_ = controller.view } 原始故事https://github.com/onmyway133/blog/issues/52