【发布时间】:2013-09-30 01:10:12
【问题描述】:
我正在编写一些包含数据库访问的代码。测试驱动开发是否包括集成测试以及通常的单元测试?
谢谢!
【问题讨论】:
标签: unit-testing tdd integration-testing
我正在编写一些包含数据库访问的代码。测试驱动开发是否包括集成测试以及通常的单元测试?
谢谢!
【问题讨论】:
标签: unit-testing tdd integration-testing
TDD 的黄金法则是:永远不要在未通过测试的情况下编写新功能。
如果您不遵守这条规则,那么您就是在部分地执行 TDD(例如只为应用程序中的几个类编写单元测试)。这总比没有好(至少你知道这些类做了需要的事情,但是你不能确定应用程序的其他部分是否在工作并且这些类可以与它们集成),但这并不能保证你的应用程序按预期工作。因此,您需要从编写失败的验收测试开始每个功能,这将指导您的应用程序设计并定义应用程序行为(外循环)。虽然此测试失败,但您的应用程序并未实现该功能。然后,您应该为将涉及此功能(内循环)的单独单元编写单元测试。外部循环验证该功能中涉及的所有类是否按预期协同工作。内部循环验证每个类是否按预期独立工作。
下图来自伟大的书籍Growing Object-Oriented Software, Guided by Tests 展示了 TDD 中的这两个反馈循环:
您的问题的答案是肯定的 - TDD 包括集成测试。只有这样才能不破坏 TDD 的黄金法则。
【讨论】:
callApi(routeName) 功能,它在内部使用getRouteConfig(routeName)。如果通过内部getRouteConfig 调用完成,我应该测试callApi 以获得正确的配置吗?
AFAIK,TDD 最初并没有区分单元测试和集成测试。就您需要设置的资源而言,集成测试的成本通常要高得多,这就是为什么即使在早期的 TDD 文献中也将模拟视为一种良好实践的原因。
来自Test-Driven Development By Example(“模拟对象”模式):
解决办法是大部分时间不要使用真实的数据库
不过,如果需要,它不应该阻止您编写一些其他测试来验证您的生产代码是否能很好地与真正的数据库或有问题的昂贵资源配合使用:
如果模拟对象的行为与真实对象不同怎么办?你可以 通过对 Mock Object 进行一组测试来减少这种策略 也可以在可用时应用于真实对象。
总而言之,我想整个集成与单元测试的事情与 TDD 是正交的。换句话说:拥有一个小的红色/绿色/重构反馈循环作为您的原子构建块并不能确定您应该选择哪种整体应用程序开发工作流程或应该围绕它的其他反馈循环 - 它可能是接受驱动的 @lazyberezovsky解释,由外而内或由内而外,以集成为中心或以隔离为中心,等等,只要你坚持测试优先的方法。
【讨论】:
我想说,在“正常”的 tdd 循环中,红 - 绿 - 重构,应该模拟数据库访问。至于这个单元测试是使用的,被测试的部分应该尽可能小。但是,每个项目都必须进行集成测试。
【讨论】:
进行测试驱动开发(而不是在编写代码之后编写测试)的主要原因之一是它helps direct low level design。就这一点而言,它必须是单元测试而不是集成测试。
【讨论】: