绝对是一个很好的清单。以下是一些关于它的想法:
先写测试,再写代码。
我同意,在高水平上。但是,我会更具体:“先编写一个测试,然后编写足够的代码以通过测试,然后重复。” 否则,我担心我的单元测试看起来更像集成或验收测试。
使用依赖注入设计类。
同意。当一个对象创建自己的依赖项时,您无法控制它们。控制反转/依赖注入为您提供控制,允许您使用模拟/存根/等隔离被测对象。这就是孤立地测试对象的方式。
使用 Model-View-Controller 或 Model-View-Presenter 将 UI 代码与其行为分开。
同意。请注意,即使是演示者/控制器也可以使用 DI/IoC 进行测试,方法是为其提供一个 stubbed/mocked 视图和模型。查看Presenter First TDD 了解更多信息。
不要编写静态方法或类。
不确定我是否同意这一点。可以在不使用模拟的情况下对静态方法/类进行单元测试。所以,也许这是您提到的 Rhino Mock 特定规则之一。
对接口进行编程,而不是类。
我同意,但原因略有不同。接口为软件开发人员提供了极大的灵活性——不仅仅是对各种模拟对象框架的支持。例如,没有接口就无法正确支持 DI。
隔离外部依赖。
同意。使用接口隐藏您自己的外观或适配器(视情况而定)后面的外部依赖项。这将允许您将您的软件与外部依赖项隔离开来,无论是 Web 服务、队列、数据库还是其他东西。当您的团队不控制依赖项(也称为外部)时,这一点尤其重要。
将您打算模拟的方法标记为虚拟。
这是 Rhino Mocks 的限制。在喜欢手动编码存根而不是模拟对象框架的环境中,这不是必需的。
而且,有几点需要考虑:
使用创造设计模式。这将有助于 DI,但它也允许您隔离该代码并独立于其他逻辑对其进行测试。
使用Bill Wake 的 Arrange/Act/Assert 技术编写测试。这种技术可以非常清楚地说明哪些配置是必要的、实际测试的内容以及预期的内容。
不要害怕推出自己的模拟/存根。通常,您会发现使用模拟对象框架会使您的测试非常难以阅读。通过自己滚动,您将完全控制您的模拟/存根,并且您将能够使您的测试保持可读性。(请参阅上一点。)
避免将单元测试中的重复重构为抽象基类或设置/拆卸方法的诱惑。这样做会隐藏试图理解单元测试的开发人员的配置/清理代码。在这种情况下,每个单独测试的清晰性比重构重复更重要。
实施持续集成。在每个“绿色条”上签入您的代码。构建您的软件并在每次签入时运行您的全套单元测试。(当然,这本身不是一种编码实践;但它是一个令人难以置信的工具,可以让您的软件保持清洁和完全集成。)