Tag: tdd

Swift中的单元测试笔尖

这是一个简短的教程,展示了如何将TDD原理应用于iOS项目中的笔尖设置,希望这将使您对一般的笔尖和TDD实践有更好的了解。 第一: 打开Xcode并创建一个新的单视图项目。 随便叫什么,但要确保启用了单元测试。 检查您的项目并删除所有样板代码。 您的ViewController应该看起来像这样:

TDD是“落后”

在向同事教授TDD时,经常会出现相同的问题: 我们从哪里开始开发软件? 这个问题导致了很多讨论和理解TDD的艰辛。 我看到了从哪里开始的不同方法,但是大多数情况下,人们倾向于使用用户界面。 这样做的原因是能够执行交互并查看他们是否实现了正确的行为。 在TDD中执行此操作非常繁琐。 您从一个按钮开始,然后检查它是否为nil。 好的,是这样……按下按钮时,我想查看用户搜索的电影列表。 嗯,我还没有测试,因为我还没有任何数据! 该怎么办? 一种选择是传入伪数据,并在每次添加一些代码时将其逐段替换为实际数据。 这似乎很好,直到您意识到需要大量工作并且开发速度缓慢。 另一种选择是不以用户界面开头。 而是从网络请求开始。 从这里开始,您的测试将确切知道预期的内容并正在测试实时数据,而不是模拟(当然,下一步是对请求进行存根,但我们还没有完成)。 编写完请求后,我们可以添加解析,然后可以添加存储等。通过这一切,我们知道我们拥有的工作代码不基于假设。 自下而上的一个问题是股东。 他们希望看到您软件中的更改,而他们看不到创建网络堆栈。 不要陷入模拟所有数据并仅创建用户界面以使股东满意的陷阱。 在某个时候,您将不得不编写其余的内容,然后他们将抱怨更多,因为开发速度很快,现在没有新内容了。 除了默认的TDD做法,这没什么别的主意: 从您所需的最小代码开始,并为此编写测试。 结论 让这个主意变得不那么容易。 它要求纪律首先编写测试,而不添加不必要的代码。 仍然遵循这一纪律并坚持下去将会产生巨大的成果,上面所写的想法只会帮助您入门。 实践TDD本身将得出这个结论。 如果不是这样,我很想听听! Next:Swift中的高级模拟 上一篇:联网怎么样?

单元测试和测试驱动开发(Xcode 8和Swift 3)

使用单元测试时,您将使用代码来测试项目,而不是运行模拟器并浏览应用程序。 在开发时,测试不是必要的做法-但是,如果您设置了良好的测试,它会使构建和重构代码更加安全。 我们可以使用代码测试代码的方法是将函数结果与预期结果进行比较。 因此,如果我们有一个函数返回两个整数的和,则可以给它提供具有预期结果的参数。 因为我们知道2 + 3 = 5…如果函数返回5,则测试将通过,否则测试将失败,并且我们知道需要修复函数。 许多开发人员练习测试驱动开发(TDD)。 TDD涉及在编写与该测试关联的生产代码之前编写测试代码。 在本文中,我将构建一个使用单元测试和TDD的简单项目。 设置项目 要在项目中使用单元测试,需要与主项目建立一个单独的目标。 您可以通过在创建新项目时取消选中“使用单元测试”框来实现。 如果您已经创建了项目,则可以通过在Project Navigator中选择项目 ,选择“ Targets”下的“ +”按钮,然后选择“ iOS Unit Testing Bundle”来创建新目标。 在这两种情况下,Xcode都会创建一个新目录,默认Info.plist和.swift文件。 .swift文件包含一些可以在XCTest框架中使用的函数示例,但是我们将从头开始创建自己的文件。 设置测试.swift文件 为了使事情井井有条,我将为项目中的每个.swift文件创建一个tests.swift文件。 为了说明这一点,我将在项目中创建两个新的.swift文件,然后再创建相应的tests.swift文件。 由于我们在这里进行TDD练习,因此让我们从为Math.swift文件中的代码创建一些测试开始。 我将跳至我的MathTests.swift文件并设置该文件进行测试。 设置tests.swift文件时,您将要导入XCTest框架和包含@testable的项目。 这允许单元测试在您的项目中查找测试中定义的任何类。 接下来,我们将该类定义为XCTestCase的子级。 我还包括一个初始变量和两个函数。 “ setUp”函数在类中的每个测试方法之前被调用,而“ tearDown”在每个测试方法的末尾被调用。 如果需要,您可以进行一些自定义-但在我们的示例中我们将不需要它们。 现在,在编写生产代码之前,我已经以真正的TDD方式编写了测试实现的一部分。 由于我的Math.swift文件没有任何代码,因此测试无法找到它。 因此,让我们转到Math.swift文件并声明该类以解决此问题。 快速构建后,错误已修复! 请记住,由于我们导入了项目,因此可以在项目中使用类声明变量。 编写数学测验 我们想要一个包含3个整数的函数,该函数获取前两个整数的和并将其乘以第三个整数。 由于我们正在练习TDD,因此让我们先编写测试。 这是测试功能的基本结构: 为了在运行测试时调用该函数,名称必须始终以“ test”开头。 这里的函数名为“ testAddAndMultiply”,因为我打算在我的数学类中创建一个名为“ addAndMultiply”的函数。 接下来,我们看到“ XCTAssert”,它实际上是一个函数。 […]

我应该使用多少个测试?

我在开始撰写此博客时就对如何提高应用程序质量进行了解释。 在途中,我们遇到了许多不同类型的测试。 但是,我们应该对每种类型的应用程序投资多少? 一如既往,需要平衡。 这次是关于我们可以投资多少与将创造多少价值(不是总是这样)。 因此,让我们详细看一下。 单元测试 我们已经对单元测试进行了很多研究。 如何在Objective-C,Swift中做到这一点以及如何测试Apple的MVC(测试UIElements时不要忘记在UIViewController上调用controller.view)。 单元测试的优势是什么? 快速 可靠(如果操作正确;) 涵盖很多部分 具有所有优势,还有什么要错过的? 他们是孤立的 不要测试零件是否装配在一起 最重要的是他们要快。 不论是10还是1000,都没关系。它们在不到几秒钟的时间内运行。 开发人员没有理由在提交更改之前不运行它们。 这很简单。 我们拥有的越多越好。 这也是我们在TDD中使用它们的原因。 确保独立编写它们。 不要使用数据库或网络。 而是存根吧! UI测试 UI测试也是一个主题。 我们已经看到了多个框架来实现它们,以及如何使它们独立于任何后端。 优点: 测试组件 您可以将它们用于验收测试 它们的行为类似于用户 与往常一样,您可以期望它们有缺点: 慢 脆弱(对应用程序的每次更改都会破坏它们) 慢(我已经提到过吗?) UI测试需要大量维护。 它们可能会随时中断,即使只是由于模拟器无法连接到Xcode也是如此。 因此,它们显示的每一次失败,可能都不是您应用程序中的错误。 您需要对其进行调查。 最重要的是,它们运行非常缓慢。 即使当告诉他们不要在测试开始时重新启动应用程序,使用模拟后端并删除动画(您仍然不应该这样做)时,它们也会永远占用。 目前,我们的50个测试需要15分钟以上的时间才能运行。 每次更改后,没有开发人员会这样做。 因此,您的CI需要。 拥有它们真是太好了。 但是请注意,它们需要大量工作。 由于测试很慢,因此不应有比单元测试多的测试。 验收测试 我们已经研究了无UI的验收测试。 使用这种类型可以实现令人难以置信的目标。 他们甚至可以帮助您与客户合作并以更精确的方式确定需求(如果您想了解与客户合作的方式,请查看BDD)。 那么为什么要使用它们: 快速(与UI测试相比) 测试整合 […]

峰值和稳定仅在以下情况下有效:

如果您正在练习敏捷,您可能知道峰值 。 这是一个有时间限制的代码实验,目标​​是学习。 丹·诺斯(Dan North)提出了一个新的概念,称为“ 峰值和稳定”。 这是一种高纪律模式,目的是通过不花时间在不重要的功能上进行测试,重构和设计,从而快速创造价值。 我们的想法始终是从一个高峰开始,我们将向用户学习,并承诺以后例如使用测试驱动开发 (TDD)来稳定它。 它可以帮助团队将重点放在对客户重要的问题上,并且如果代码没有带来任何价值,也可以避免丢掉代码。 我发现这种方法非常有效,另一方面,我对将凌乱的代码创建到生产代码中并在以后使其稳定的想法感到不满意。 我是Robert C Martin如何描述专业开发人员的忠实拥护者: 专业开发人员切勿推动任何未经测试的代码生产线。 -罗伯特·C·马丁(鲍勃叔叔) 我认为只有将尖峰与生产代码隔离开,S pike和Stabilize才能起作用。 当需要稳定它时,使用TDD,SOLID原理并对其进行清理很容易将实际代码移入生产环境。 在iOS开发中,使用Swift Playground可以很容易地将尖峰与生产代码隔离开。 苹果在博客文章中将其描述为: 交互式游乐场可以帮助您快速原型化和构建应用程序,并提供另一种与代码交互的好方法。 通过与生产代码隔离的原型来探索新功能,使开发人员可以从可行的投资中寻求可行的回报 。 肯特·贝克(Kent Beck)在他的3X概念中对此进行了描述: 冒险寻求可行投资的可行回报。 成功的勘探是无法预测的,因此最高的期望值策略是降低实验成本,并为许多不相关的实验投入少量资金。 如果您幸运的话,这些实验之一证明是出乎意料的成功 最后,我认为所有iOS开发人员都应始终从Swift Playground页面开始,然后将代码拉成看起来像是首先经过测试驱动的形状 🤫。 丹·诺思(Dan North)在GOTO会议上谈论尖刺和稳定(15:50至27:30) 肯特·贝克(Kent Beck)谈论3X概念(始于20:21) 布兰登·威廉姆斯在FrenchKit会议上谈论操场驱动开发 如果您认为这将有助于其他开发人员更好地开发产品,请随时发表评论和分享。

为什么我要编写快照测试?

测试是任何高质量软件的组成部分。 我相信每个公司或软件发行商都必须先验证产品的质量,然后才能投放市场。 据说,如果质量好,它将吸引更多的用户。 这个事实也适用于软件开发。 我们以手动或自动方式执行UI测试,以确认应用程序的行为正确并具有符合规范的所有功能。 如果我们进行更细化的单元测试,则可以测试单个单元。 我们通过编写肯定的测试(即正确通过测试)和否定的测试(即测试意外数据到来时单元的行为)来涵盖所有极端情况。 编写自动化测试以捕获UI“正确性”实际上是不可能的。 测试UI困难的原因是,UI最小模块的显着细节很难以编程方式表达。 正确性不能由输出的文本部分确定。 我们希望质量保证将重点放在需要人工关注或可以通过自动化完美测试的功能的确切状态下的确切组件上。 但是UI单元测试呢? 好吧,我们为此提供了一个解决方案: 快照测试! iOSSnapshotTestCase如何捕获快照? iOSSnapshotTestCase提供FBSnapshotVerifyView(view)方法来将期望与参考快照进行比较。 如果不存在参考快照,它将捕获。 这个方法使用`renderInContext()`来捕获快照,但是`renderInContext()`有一些限制,您不能使用它来测试Visual元素或UIAppearance。 为了测试这些元素,还有另一种方法“ drawViewHierarchyInRect”。 要使用此方法,您需要在测试中设置`useDrawViewHierarchyInRect = true`。 drawViewHierarchyInRect的性能不好,所以我建议仅在确实需要时使用useDrawViewHierarchyInRect = true。 iOSSnapshotTestCase如何比较快照? 有很多比较图像的方法。 我在演讲中得到的第一个答案是逐像素比较图像,这是正确的,但在逐像素比较之前,我们还需要考虑其他方面。 让我们看看它如何进行比较: 首先,它比较图像大小。 如果不匹配,则测试失败。 如果容差率为零,则使用C函数“ Memcmp()”在内存级别比较图像。 为此,它使用calloc()在内存中分配空间,并使用CGContextRef在内存中绘制图像。 如果容差率> 0,即表示您可以接受,即使存在x%的差异,它也会通过对numberOfPixels(即图像宽度*高度)进行迭代来逐像素比较图像。 iOSSnapshotTestCase的功能: 它会根据测试类和选择器自动命名磁盘上的参考映像。 如果要在单个测试方法中执行多个快照,则需要提供一个可选的“标识符”。 使用`isDeviceAgnostic`。 如果您在测试中将此属性设置为true,它将在测试名称中附加设备型号,操作系统编号和大小。 优点: 快照测试易于编写。 在执行重构时,您不必担心,就好像只有代码重构一样,测试也不会失败。 解耦:视图将松散耦合。 易于验证不同尺寸的布局。 我建议以一个模拟器(即iPhone 6)为基础来捕获快照。 如果您使用3倍快照的iPhone 8,则尺寸会很大。 如果您使用的是CI / CD工具,请确保也在那里设置了默认模拟器iPhone 6。 […]

创建ReactiveSwiftRealm-第2部分

在第1部分中,我解释了如何创建与Carthage,Cocoapods和子模块兼容的基础项目。 现在是时候编写代码了。 在最初的帖子中,关于合并ReactiveSwift和Realm的过程中,我解释了我想要获得的东西,这是第一步。 我想要一个围绕Realm基本操作的反应式包装器。 让我们从添加操作开始。 我是TDD的忠实拥护者,所以我将从Realm add操作开始在这里应用它。 在测试之前,我们应该将在主要目标上拥有的相同链接框架添加到测试目标。 如果我们不这样做,将会得到奇怪的Xcode错误。 我只需要围绕该简单任务的反应式包装,以便可以在反应式上下文中轻松使用它。 我最需要的是什么? 一个保存方法,该方法返回SignalProducer 为了测试我需要 调用某些东西,它应该返回SignalProducer 我的测试结束是这样的: 当然,它会失败,这是我应该在TDD中期望的(现在看起来很愚蠢,但是由于代码库很大,您可能会编写测试代码,并且在您期望测试失败时第一次通过测试。看到测试失败也是重要),因此请对其进行修复,使其通过测试(仅此而已)。 在ReactiveSwiftRealm组中,我将创建一个ReactiveSwiftRealm.swift文件,其中包含通过测试所需的代码: 导入ReactiveSwift 导入结果 func add()-> SignalProducer { 返回SignalProducer(值:()) } 我需要一个函数来返回SignalProducer,这就是我得到的。 现在,我必须在测试中导入ReactiveSwift和Result,以便它知道什么是SignalProducer,然后运行测试。 通过第一个测试,我必须考虑我需要的下一个功能。 SignalProducer应该保存一个Realm对象 好的,因此我需要保存对象,并且需要添加功能来获取该对象并将其保存。 让我们编写测试代码! 好的,再次失败,正如预期的那样。 (是的,您可以庆祝某些事情行不通)。 让我们修复它: 导入RealmSwift 按照Realm步骤创建FakeObject类 FakeObject类:Object { 动态var id =“” } 更改添加函数,使其带有对象类型参数(您也需要在添加声明文件中导入RealmSwift) 现在,我们将看到我们的第一个测试失败,我们已经更改了函数声明,因此可以预期会失败。 只需对其进行更改,使其也需要一个伪造的对象。 现在我们的第二项测试失败了。 为什么? 好吧,它什么都不保存,所以让我们更改add函数,以便保存对象。 我们将在这里找到并发布,我们需要一个领域参考才能将该对象存储在数据库中。 好的,让我们在add函数中添加一个realm参数,以便我们可以在内部使用它。 当然,由于我们再次更改了功能,两项测试都将失败。 由于我们在两个测试中都需要一个领域实例,因此我将在ReactiveSwiftRealmTest级别上创建它,以便可以在任何测试中使用它。 我将使用领域测试功能,该功能允许我使用内存中领域(而不是真实的数据库): 覆盖func setUp(){ […]

为什么要编写单元测试?

作为软件工程师,我们总是编写代码,但是测试代码又如何呢? 当有人要求您编写单元测试时,还有更多的执行程序。 1,我不知道怎么写单元测试 2,写作单元测试是如此艰难 3,我的代码太简单了,无法测试 4,我没有足够的时间编写单元测试。 ………………………………。 不 没有人喜欢写它。 如果您想编写测试代码来确保您的代码,以减少奇怪的错误。 首先,您必须选择出色的建筑。 MVC怎么样? 1,大量的viewController 除非您是初级ios开发人员,否则请放弃,否则您将永远不会这么做。 众所周知,MVC意味着Massive ViewController,它承担着更多的责任,因此它违反了单一原则,您可以让它承担更多的任务。作为高级开发人员,我们必须编写符合SOLID RULES的代码-确保您的代码具有高品质,如果您总是写不好的代码,如何提高自己的技能。 这里我没有提到编写干净代码的主题,但是,如果您学习它,可以阅读本书的名字Clean coder,作者将他的最佳实践贡献给我们,谢谢他。 清洁编码员:培训视频。 具有个性。 对于软件专业人员。 Clean Coders是为软件专业人士提供指导性视频的领先制作人,其教学方式可同时兼顾… 2,艰难测试 因此,我们开始从Microsoft公司+ RxSwift + Coordinator中选择另一个著名的MVVM。 还有更多博客要写,所以我不提它…… 众所周知,还有更多的博客谈论架构,但这并不完美。重要的是您要在项目中使用哪个角色…… 几天来,我写了一篇有关清洁架构的博客,我认为架构的重点是您必须对其进行设计……设计—使您的业务清晰明了…… 为什么要编写单元测试? 1,测试减少新功能中的错误 我们提倡在编写新代码时编写测试。 测试不能消除错误,但是随着您添加新功能,它们会大大减少错误的数量。 2,测试减少现有功能中的错误 使用经过良好测试的代码,引入新功能很少会破坏现有功能。 如果一项新功能破坏了现有功能,则现有测试将立即失败,从而使您可以找出问题并加以解决。 没有测试,您可能会引入几天或几周内找不到的错误。 3,测试是一个很好的文档 简洁的代码示例胜于文档的许多段落。如果阅读文档,我们总是在不同文件之间来回移动。 4,测试是如此有趣 如果您想挑战自己,写作测试将非常有趣…… 5,测试改善你的设计 编写测试会迫使您使代码可测试。 具体来说,您倾向于较少依赖诸如单例和全局变量之类的可疑模式,而是使类松散耦合且更易于使用。 紧密耦合的代码或需要复杂初始化的代码很难测试。 6,测试使开发更快 众所周知,测试可以减少错误,我们将大部分时间花在调试应用程序上。10%的时间编写代码,当您的代码变得越来越多时,错误很难调试,因此这会减慢您的开发速度。 7,测试可以迫使自己放慢脚步思考 开发人员总是先犯一个常犯的错误,然后立即开始编写代码……愚蠢的行为要做,这会使您感到痛苦。 8,测试减少恐惧。 如果您从未编写过Test,如何知道您的应用程序运行良好。所以让您远离恐惧,今天就开始编写Unit test。 […]

TDD迅速UygulamaGeliştirmeninfaydalarıve Xcode da Swift迅速XCTestkullanımı

测试驱动开发(TDD)可以帮助您完成测试驱动开发(TDD) 。 Genellikleyanlışbirkanıolarak单元测试yazmanınuygulamageliştirmesüresiniuzatacağıdüşünülüyor。 Halbukiuygulamamızdaöncedenunit testleriyazılmasıdaha kolay birşekildeyapılacakişlevintasarlanabilmesinisağlar。 布达下摆tasarım下摆işlevintestinde bize zamankazandırdığıgibi kodu daha iyiyapılandırabilmemizede olanaksağlar。 Bu nedenle unit testler ile uygulamageliştirmemizdaha sonraoluşacakmuhtemelbuglarıdaöncesindetespitedebileceğimiziçinuygulamageliştirmesüresiniazaltacaktır。 Uygulamamızınkod kalitesiniartırarakdaha az bir bug ilegeliştirebiliriz。 单元测试器下摆pozitif下摆negatif caseler ile beraberyazdığımızdaolabilecekbirçokfarkli案例测试etmeolanağınakavuşmuzoluruz。 Buda iyi testedilmişve daha az bugiçerenkodyazmamızısağlayacaktır。 Yazdığımız单元测试仪daha sonra uygulamadakioluşabilecekdiğerbuglarıtespit etmemizde bizeoldukçakolaylıksağlayacaktır。 Budauygulamamızdakigelecek olanbuglarıçözmesüremiziönemliölçüdeazaltacaktır。 Teamcity gibi CI( Continus Integration)单元测试人员, Jenkins单元, 测试系统(SUT)(测试中) prensibine uygunsürekliolarak测试,edilen biruygulamamızolur。 Projedeyapılan她的承诺sonrasındaunit […]

专业的iOS工程YouTube系列

我们非常高兴与您分享我们的新系列专业iOS工程第1季的发布-在Essential Developer的Youtube频道上使用TDD和模块化设计构建Swift应用 。 在Caio和Mike的一对编程系列中,将演示测试驱动开发的原理, 模块化系统的功能以及如何满足未来的需求 。 他们保持可持续的发展周期,并不断思考如何提高效率,同时注意技术优势和良好的设计 。 该系列专为希望将其技能提升到更高水平的专业人士和有抱负的iOS开发人员而创建。 Caio和Mike尝试推理并解释他们做出的大多数决定,并努力为问题提供多种解决方案。 立即订阅我们的Youtube频道, 每周获取免费的新剧集,并在Github上关注该项目的进展。