将测试驱动开发应用于紧耦合架构

时间:2010-03-23 16:28:11

标签: c# .net unit-testing architecture tdd

我最近一直在研究TDD,参加了一个会议,并且已经进行了几次测试,并且已经100%销售,我绝对喜欢TDD。

结果我和老年人一起提出了这个问题,他们准备给它一个机会,所以他们让我想出了在企业产品开发中实施TDD的方法。

问题是我们的系统自从VB6发展到.NET以来已经发展并实现了许多遗留技术和一些远离最佳实践的开发技术,即ASP.NET代码背后的许多业务逻辑和客户端脚本。然而,最大的问题是我们的类如何与数据库访问紧密结合;属性,方法,构造函数 - 通常以某种形式或某种形式访问某些数据库。

我们使用内部数据访问代码生成器工具创建sqlDataAdapters,为我们提供了我们可能想要的所有数据库访问权限,这有助于我们快速开发,但是,业务层中的类与这些数据紧密耦合layer - 我们甚至没有接近实现某种形式的存储库设计。这和上面的问题给我带来了各种各样的问题。

我已经尝试为我已经编写的一些现有类开发一些单元测试但是由于需要db访问,所以测试需要更长的时间才能运行,更不用说因为我们使用MS Enterprise Caching框架我被迫伪造一个httpcontext让我的测试成功运行,这是不切实际的。另外,我无法看到如何使用TDD来驱动我编写的任何新类的设计,因为它们必须与数据库紧密耦合......帮助!

由于系统的体系结构,我觉得如果没有一些真正的黑客攻击,我就无法实现TDD,在我看来,这只会破坏TDD的目标以及带来的巨大好处。

有没有人有任何建议我如何使用我必须约束的TDD来实现?或者我是否需要将存储库设计模式推向我的老年人喉咙并告诉他们我们要么改变我们的架构/开发方法还是完全忘记TDD? :)

由于

4 个答案:

答案 0 :(得分:9)

只是澄清一下,测试驱动开发和单元测试不是一回事。

  • TDD =在代码前写下您的测试。
  • 单元测试 =编写确认一小部分代码的测试。
  • 集成测试 =编写确认代码块协同工作的测试。
根据定义,TDD无法在现有代码上完成。您已经开发了代码,因此您不会再次开发它。 TDD意味着您首先编写失败的测试,然后您编写足够的代码来通过测试。你已经编写了代码,所以你不能做TDD。

您可以为现有代码编写单元测试,但这与执行TDD不同。

您描述的测试(访问数据库等)是技术上的集成测试。集成测试通常需要很长时间才能运行。真正的单元测试将纯粹测试您的DA层代码而无需实际访问数据库。真正的单元测试需要测试接口,以便您可以将单元与周围单元隔离。

正确地对现有代码进行单元测试是非常困难的,除非它在设计时考虑了接口和抽象。

我知道我在这里的术语略显挑剔,但是在你采取什么方法时这很重要。我的建议是,对于现有的代码,如果没有很好的抽象,你应该逐步构建一套自动化集成测试。当你来写一些新东西(可能不是一个完整的项目,它可能只是现有应用程序的新部分)时,考虑以TDD风格接近它。为此,您将发现需要编写一些接口和抽象,以允许您在新代码上执行TDD而不会触发太多现有代码。然后,您将能够编写一些集成测试,以测试使用旧代码的新代码。

简而言之 - 不要试图改变现有代码的方法。只是做更好的新代码。

答案 1 :(得分:6)

Nitpick:您不能对现有代码进行Test- Driven 设计,但我确实意识到您希望将TDD用于在现有代码库上实现的新功能。

您可以做的最好的事情是逐渐接缝引入代码库,使您免受已存在的紧密耦合代码的影响。

本书Working Effectively with Legacy Code包含很多关于如何将遗留应用程序转换为可测试应用程序的建议。

答案 2 :(得分:1)

我认为您使用ASP.NET Web Forms的这一事实将成为您TDD之路的挑战。在Web窗体中模拟Session / ViewState / HTTPContext只是一场噩梦,因此测试驱动几乎是一个障碍。当然还有ASP.NET MVC的替代方案,但你似乎已经开始了。 Web窗体范例的另一个有希望的选择是ASP.NET Web Forms MVP,但该项目尚未完全成熟。我正在尽我所能去MVC;使用Web窗体Selenium的TDD的另一个选项实际上并不是TDD。

答案 3 :(得分:0)

要将测试添加到现有代码,您可以查看Working Effectively With Legacy Code。 “遗留代码”被定义为没有测试的代码。