如何在Swift中编写可测试的代码

Hon*_*ney 15 tdd unit-testing functional-programming design-guidelines swift

所以我的这个问题都开始了,当我开始对一个简单的2行postNotificationaddObserver.从这个类似的问题,你可以看到,为了使它可测试你需要添加~20行部分远离编写代码的常用方法.

面对这个问题实际上是我第一次理解单元测试和TDD之间的区别.如果您的代码是可测试的,即如果您遵循TDD思维模式,则单元测试很容易.接下来我被问到如何编写可测试的代码,我没有找到太多的指导原则,每个教程只是跳到编写单元测试.Apple自己的文档没有任何内容.

我最初的想法是,我需要以"函数式编程"为目标,并以纯函数的方式编写我的函数.但是,这又是非常耗时的,并且可能需要在现有代码中进行大量重构,甚至对于新项目需要大量添加的行,我甚至不确定这是否是正确的方法.是否有任何建议的指南或标准可以轻松编写可测试代码?

我已经知道的了:我知道你不应该编写任何代码,除非有测试失败,所以基本上我必须先编写测试,一旦出现错误,即使是编译器错误然后我会切换回实际的类被测试写入任何必要让我的测试代码不给任何错误,然后再切换回测试类,并继续写我的测试和修复编译错误,直到完成.然后运行测试,看看它是否检查我想要检查的内容.

对于所有测试,我应该确保我的测试通过并且确实在我预期失败的地方失败,即测试将在预期失败时通过.

我不知道的是如何以更简单的方式平滑过程.

我不是要求如何编写NSNotificationCenter的可测试代码,我要求编写可测试代码的一般准则.

mz2*_*mz2 16

这是一个相当大的问题,也是开发者的观点向不同方向发展的问题.同样重要的是要注意,使代码可测试是在很多基本方面,而不是Swift特定的问题:很多使你能够定期和方便地编写可测试代码的东西实际上依赖于你遵循一些基本的,普遍适用的原则.通常,测试驱动的设计实践可以间接地帮助您,通过验证您已经遵循通过测试合理执行代码的实践,同时为您带来其他程序员的生产力和可靠性优势.因此,遗憾的是,编写可测试代码不是学习使用Xcode的一些机械技巧的问题,而是通常证明您已经设计和规划了您编写的程序和库,并保留了一些良好实践.

我将尽力将下面链接到一些Swift特定资源,以演示我倾向于遵循的更一般的原则,以使我的代码可测试.

  1. 使代码可测试通常是遵循声音面向对象设计原则的副作用.

  2. 遵循良好的面向对象设计通常本身就是良好的更高级别架构决策的副作用.基本上,请尽早思考并经常考虑您计划在程序的对象图中引入的类型.它们之间的角色和依赖关系是什么?从不同的上下文(例如,从UI代码到单元测试)执行代码时,对象图中的任何依赖项难以满足或正确构造吗?

    • 有很多关于建筑设计模式的计算机科学文献.四人帮仍然是一本有关这个主题的宝贵书籍(尽管并非所有这些都适用于您的典型Swift计划).
    • 看一下这个Swift设计模式演示,概述可以在Swift中实现多少常见设计模式.
    • 特别是如果你的代码是用于移动应用程序,你应该阅读VIPER,一个面向移动应用程序的架构模式出现在iOS应用程序的典型架构需求之外.
    • 为了将设计模式与上面列出的SOLID原则联系起来,"单一责任"原则可能是许多大型Cocoa程序中最明显违反的一个原则,这是由于糟糕的架构实践导致的,也导致了很难测试代码.事实上,人们经常开玩笑地将MVC称为Cocoa中的实践应用为"大规模视图控制器".

提出的上述观点绝不是斯威夫特特有的,我希望不会有非常有争议的主张.然而,Swift还提供语言功能,这些功能也可以帮助您编写可靠的无错代码,部分原因是这些语言功能可以帮助您进行友好的代码测试.这里有一些很好的Swift实践:

  • 尽可能使用值类型:Swift非常适合编写最小化自动引用计数引用(指针)的程序.这带来了性能优势,但也提高了编写可靠代码的机会,最大限度地减少了在测试中难以捕获的意外依赖性和数据竞争.
  • 尽可能保持不变:Swift中的语法约定和类型系统可以帮助您避免可变状态,这会对代码的可测试性产生负面影响(配置对象图进行测试可能会变得很困难,实现真正的如果程序中的可能状态空间很大,则代码的世界可用测试覆盖率.
  • Apple还就价值类型和不变性的架构问题提供了一些指导,这些指导也涉及代码的可测试性.
  • 在可以的时候使用协议:了解原因,阅读Liskov替换原则 :-)更严重的是,优先使用协议而不是具体类型可以帮助您编写可测试代码,例如允许您在测试特定类型的测试设置中实现依赖性伪造或模拟一些与您的测试无关的资源.
  • 使用函数式编程技术(当它有意义时):通常用函数编写功能可以帮助您编写可读,灵活的代码,避免可变状态.我推荐Chris Eidhof和其他人的Functional Swift作为在Swift中应用函数模式的一个很好的指南.

同样,这个问题很大,我只是在表达我的答案,为了表明没有单一的灵丹妙药可测试性 - 这是你在设计代码时遵循许多最佳实践的结果.