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