我正在处理一些包含数据库访问的代码。测试驱动开发是否包括集成测试以及通常的单元测试?
谢谢!
TDD 的黄金法则是:永远不要在未通过测试的情况下编写新功能。
如果你没有遵循这条规则,那么你就是在做部分 TDD(比如只为应用程序中的几个类编写单元测试)。这总比没有好(至少你知道这些类做了需要的事情,但是你不能确定应用程序的其他部分是否在工作并且这些类可以与它们集成),但这并不能保证你的应用程序按预期工作。因此,您需要从编写失败的验收测试开始每个功能,这将指导您的应用程序设计并定义应用程序行为(外循环)。虽然此测试失败,但您的应用程序并未实现该功能。然后,您应该为将涉及此功能(内循环)的单独单元编写单元测试。外部循环验证该功能所涉及的所有类是否按预期协同工作。
以下来自伟大著作《Growing Object-Oriented Software, Guided by Tests 》的图片展示了 TDD 中的这两个反馈循环:
您的问题的答案是肯定的 - TDD 包括集成测试。这是不破坏 TDD 黄金法则的唯一方法。
AFAIK, TDD originally didn't distinguish between unit tests and integration tests. It remains that an integration test is generally much more costly in terms of resources you need to set up, which is why mocks were identified as a good practice even in early TDD literature.
From Test-Driven Development By Example ("Mock object" pattern) :
The solution is not to use a real database most of the time
Still, it shouldn't prevent you from writing a few other tests that verify if your production code plays well with the real database or expensive resource in question, if needed :
What if the mock object doesn't behave like the real object ? You can reduce this strategy by having a set of tests for the Mock Object that can also be applied to the real object when it becomes available.
All in all, I guess the whole integration vs unit test thing is orthogonal to TDD. In other words : having a small red/green/refactor feedback loop as your atomic building block doesn't determine which flavor of overall application development workflow you should pick or which other feedback loops should surround it - it could be acceptance driven as @lazyberezovsky explained, outside-in or inside-out, integration-centered or isolation-centered, etc, as long as you remain truthful to the test-first approach.
我会说在“正常”的 tdd 循环中,红-绿-重构,应该模拟数据库访问。至于这个单元测试是使用的,被测试的部分应该尽可能小。但是,每个项目都必须进行集成测试。
进行测试驱动开发(而不是在编写代码后编写测试)的主要原因之一是它有助于指导低级设计。就这点很重要而言,它必须是单元测试而不是集成测试。