我应该先为视图层编写测试(在 TDD 之后)还是只进行手动测试并在完成后添加快照测试?

Should I write tests first (following TDD) for the view layer or only do only manual testing and add snapshot tests when finished?

正如预期的那样,我通常在使用视图层遵循 TDD(即首先编写测试)时遇到困难。

也就是说,为了观察或触发某些可见的变化(布局或样式),我需要制作视图的内部结构 public。这会破坏封装并允许客户端代码执行类似 myView.label.text = "User" 的操作。

为了避免这种情况,我将 getter 方法添加到 UIView class:

var userName: String{ return label.text }

或者做一些只添加到测试框架的扩展:

extension MyView{

//avoids making a getter just for the sake of testing, while keeping it private and interchangeable
var userName : String{
   return (viewWithTag(someLabelTage) as! UILabel).text
} 

另一种方法是跳过 TDD 工作流程(即在功能完成后手动测试)并添加快照测试(参见 https://github.com/pointfreeco/swift-snapshot-testing)以增加覆盖率并在重构时拥有安全网。

考虑到所有这些,我想知道是否有任何其他模式或方法可以用来提高效率,同时保持对代码的信心。

不是 Swift 方面的专家,但不管 language/framework 是什么,有件事告诉我你实际上让你的任务变得更难了。

I normally have difficulties when following TDD with the view layer.

这是意料之中的。 View 支持简单且完全没有行为(即域逻辑)。它应该是简单的用户交互,并将数据绑定到视图中的控件。因此,在我看来,您不需要 TDD 或围绕视图进行更精确的单元测试。尝试为视图编写单元测试不会获得太多价值。

使用 UI 测试框架(例如 Selenium)或您自己的 UI 测试用户交互的测试框架,可以更有效地测试您的视图。这样一来,与尝试对视图层进行 TDD 相比,您的投资 (ROI) 更多 return。

我对 Spock 的回答没什么要补充的。应该编写测试以帮助将来开发和维护代码。如果他们妨碍了,那么要么代码架构不正确,要么是投资回报率低的代码。

一个值得一提的模式是humble view。有几种方法可以实现它,每种方法都有不同的权衡,但要点是让数据结构定义视图的外观,然后让视图读取这些数据结构并从中设置其属性。

这使您可以测试驱动视图的数据结构是否正确生成,而不必测试视图本身,因为它只是一个读取和设置值的不起眼的对象。