绝对是一个很好的清单。这里有几点想法:
先写测试,然后是代码。
我同意,在高层次。但是,我会更具体一些:“先写一个测试,然后写出只需要代码来通过测试,然后重复。”否则,我会担心我的单元测试看起来更像集成或验收测试。
使用依赖注入的设计类。
同意。当一个对象创建它自己的依赖关系时,你无法控制它们。反转控制/依赖注入为您提供了该控件,允许您使用mocks/stubs /等隔离被测对象。这就是你如何独立地测试对象。
使用Model-View-Controller或Model-View-Presenter从其行为中分离出UI代码。
同意。请注意,即使是演示者/控制器也可以使用DI/IoC进行测试,方法是将其呈现为残留/模拟视图和模型。查看Presenter First TDD了解更多。
不要编写静态方法或类。
不确定我是否同意这一点。可以在不使用mock的情况下对静态方法/类进行单元测试。所以,也许这是你提到的那些Rhino Mock特定规则之一。
编程接口,而不是类。
我同意,但原因稍有不同。接口为软件开发人员提供了极大的灵活性 - 除了支持各种模拟对象框架之外。例如,无法在没有接口的情况下正确支持DI。
隔离外部依赖关系。
同意。使用界面隐藏外部依赖关系(如适用)。这将允许您将软件与外部依赖关系隔离,无论是Web服务,队列,数据库还是其他内容。这是,尤其是当你的团队不控制依赖(a.k.a. external)时很重要。
标记为您想要模拟的方法。
这是Rhino Mocks的局限性。在一个喜欢手工编码存根的模拟对象框架环境中,这不是必需的。
而且,一对夫妇的新需要考虑的要点:
使用造物设计模式。这将有助于DI,但它也允许您隔离该代码并独立于其他逻辑进行测试。
使用Bill Wake's Arrange/Act/Assert technique编写测试。这项技术非常清楚需要什么配置,实际测试的内容以及期望的内容。
不要害怕推出自己的嘲笑/存根。通常,您会发现使用模拟对象框架会让您的测试难以理解。通过滚动你自己,你可以完全控制你的模拟/存根,并且你将能够保持你的测试可读性。 (请参阅前一点。)
避免将单元测试中的重复重构为抽象基类或设置/拆卸方法的诱惑。这样做会隐藏来自开发人员的配置/清理代码,以尝试单元测试。在这种情况下,每个单独测试的清晰度比重构重复更重要。
实施持续集成。在每个“绿色栏”上签入您的代码。构建您的软件并在每次签到时运行全套单元测试。 (当然,这本身并不是一种编码习惯,但它是保持软件清洁和完全集成的一个令人难以置信的工具。)
这是一个有用的列表。我们目前正在使用NUnit和Rhino.Mocks,对于不太熟悉单元测试这一方面的团队成员来说,明确这些标准是很好的。 – 2008-09-24 13:38:02