现代用户界面,尤其是 MacOS 和 iOS,有很多“休闲”动画——通过主要由系统编排的简短动画序列出现的视图。
[[myNewView animator] setFrame: rect]
有时,我们可能会有一个稍微复杂一点的动画,带有一个动画组和一个完成块。
现在,我可以想象这样的错误报告:
嘿——新版本中没有出现 myNewView 出现时的漂亮动画!
所以,我们希望单元测试做一些简单的事情:
- 确认动画发生
- 检查动画的持续时间
- 检查动画的帧率
但是当然,所有这些测试都必须易于编写,并且不能使代码变得更糟;我们不想用大量测试驱动的复杂性破坏隐式动画的简单性!
那么,什么是 TDD 友好的方法来实现休闲动画测试?
单元测试的理由
让我们举一个具体的例子来说明为什么我们需要一个单元测试。假设我们有一个包含一堆 WidgetView 的视图。当用户通过双击创建一个新的 Widget 时,它最初应该看起来很小且透明,并在动画期间扩展为完整大小。
现在,我们确实不想对系统行为进行单元测试。但这里有一些可能出错的地方,因为我们把事情搞砸了:
动画在错误的线程上调用,并且不会被绘制。但是在动画的过程中,我们调用了 setNeedsDisplay,所以最终小部件被绘制出来了。
我们正在从废弃的 WidgetController 池中回收废弃的小部件。NEW WidgetViews 最初是透明的,但回收池中的一些视图仍然是不透明的。所以褪色不会发生。
在动画完成之前,一些额外的动画会在新小部件上开始。结果,小部件开始出现,然后在稳定下来之前开始抽搐和短暂闪烁。
您对小部件的 drawRect: 方法进行了更改,新的 drawRect 很慢。旧动画很好,但现在一团糟。
所有这些都将在您的支持日志中显示为“create-widget 动画不再起作用”。我的经验是,一旦你习惯了一个动画,开发人员很难马上注意到一个不相关的变化破坏了动画。这是单元测试的秘诀,对吧?