在旧的Java应用程序上采用TDD

时间:2010-12-01 19:52:20

标签: java testing web-applications

我遇到了问题,我正在向你寻求帮助

我已经开始研究没有测试的Web应用程序,它基于spring 2.5和hibernate 3.2,模块化程度不是很高,类有多达5k行,因为视图技术有JSP遍布全部有很多东西重复的地方(就像许多差异较小但共享部分不多的类似搜索表单一样)。

应用程序运行良好,但是,一切运行得很好,但是当需要添加或更改某些功能时,它实际上很慢并且不太方便。

此时是否有可能采用TDD?或者你会推荐什么,因为我不认为我可以像现在这样永远地发展它,它总是变得更加混乱。

谢谢你的回答。

6 个答案:

答案 0 :(得分:4)

我首先要拿一本Michael Feathers的书Working Effectively with Legacy Code - 这是纯金。

一旦你学习了重构和拆分应用程序的逻辑接缝技术,你就可以在更新的模块/萌芽类和方法等中集成TDD。

例如,我们最近转而使用TDD方法来编写几乎每个版本的框架中使用的十年历史的应用程序,虽然我们仍在努力处理某些部分,但我们已确保所有新的工作被抽象出来,所有新代码都在测试中。

如此绝对可行 - 只是更具挑战性,上面的书可以帮助您入门。

答案 1 :(得分:3)

首先,欢迎那些必须解决他们更糟糕的同事所做的犯罪的优秀程序员的俱乐部。 :(

我有过这样的经历。在这种情况下,推荐的做法之一是开发新功能的测试。您现在无法停止并为整个应用程序开发测试。你可以做的就是每次你必须为这个功能编写新的功能开发测试。如果此功能需要在某些敏感位置进行更改,请启动对这些位置的测试。

重构是一个大问题。理想情况下,如果你想将5k行类分成10个普通大小类,你应该首先为大类开发测试用例,然后执行refatoring然后再次运行测试以验证你没有破坏任何东西。这在实践中非常困难,因为当您更改设计时,您更改了界面,因此您无法运行完全相同的测试。因此,每次你应该做出艰难的决定什么是最好的方式,什么是覆盖你的屁股的最小测试用例。

例如,有时我进行了5阶段反射: 为不良大班制定了测试 2.开发了新的精心设计的代码,并将旧类更改为我的新代码的外观。 3.运行在#1中开发的测试用例来验证一切正常 4.开发了新的测试,验证每个新的(小)子模块是否运行良好 5.重构代码,即删除所有对旧的旧类(对于轻量级外观)的引用 5.删除了旧班及其考试。

但这是最糟糕的情况。当我要更改的代码非常敏感时,我不得不使用它。

很快,祝你工作顺利。准备一夜之间工作,然后收到来自QA的20个错误报告和来自老板的愤怒电子邮件。 :(坚强。你是正确的方式!

答案 2 :(得分:2)

如果您因为害怕破坏而无法进行任何更改,那么您已经回答了自己的问题:您需要做点什么。

洞的第一个规则是:如果你被困在一个洞里,就停止挖掘。

您需要建立一个策略,以便在没有测试的情况下提交代码,这是例外,而不是规则。使用持续集成并强制人们保持构建通过。

我建议首先在测试中捕获应用程序的核心功能,包括单元和集成。这些测试应该是一个基线,显示必要的功能正在运行。

你提到有很多代码重复。这是下一个去的地方。在具有重复代码的区域周围进行测试。您将在此处测试2个或更多项目,因为存在重复。然后做一个重构,看看测试是否仍然通过。

一旦你敲下一张多米诺骨牌,剩下的就会跟着。

答案 3 :(得分:1)

是的,TDD肯定有一席之地,但它只是解决方案的一部分。

在进行任何更改之前,您需要refactor此应用程序。重构要求测试覆盖范围到位。取一小部分显然不合标准的代码并为它们编写characterisation测试。这意味着您可以通过该代码测试所有可能的变体。你可能会发现这样做的bug。通过你的质量保证系统提出错误并暂时保持错误行为(用你的特征测试锁定错误,因为系统的其他部分可能现在依赖于错误的行为)。

如果您有非常漫长而复杂的方法,您可以在适当的时候调用IDE来提取小部分以分离方法。然后为这些方法编写特征测试。以这种方式一点一点地攻击大方法,直到它们被很好地分区。最后,一旦你有适当的测试,你就可以重构。

在这种情况下,

integration测试可用于突出显示快乐日场景或一些主要错误场景。但通常在这种情况下,应用程序太复杂,无法编写完整的集成测试套件。这意味着您可能永远不会仅使用集成测试100%保护免受副作用。这就是为什么我更喜欢'提取方法'和表征。

既然您的应用程序不受副作用的影响,您可以使用TDD添加新功能。

答案 4 :(得分:0)

我的方法是开始逐个添加测试。如果有一个部分你知道你将不得不在不久的将来更新,那么就开始对该部分进行一些很好的报道。然后,当您需要更新/重构时,您将进行回归测试。从它的声音来看,建立一个综合测试套件将是一项重大任务,但它最终可能会得到回报。我还建议使用各种代码覆盖工具之一来查看您的测试实际覆盖了多少。

干杯!

答案 5 :(得分:0)

此时您可能无法进行测试驱动开发,除非您碰巧添加了易于与系统其他部分隔离的功能(这是不太可能的)。

但是,您可以(并且应该)确定添加核心功能的自动化测试。在单独测试小单位代码的意义上,这些最初不会是真正的单元测试,但IMO的重要性往往被夸大了。 集成测试可能无法快速运行或帮助您快速查明错误原因,但它们仍然可以极大地帮助您保护您免受更改的副作用。当你重构代码以使未来的更改更容易并且真正的单元测试成为可能时,这是你真正需要的东西。

一般情况下,首先选择低挂多汁的水果:为可以轻松测试的部分代码编写测试,或者轻松破解,或者在破坏时导致大多数问题(以及因此,测试是最有价值的,或者理想的是所有这些都在一起。这可以快速为您提供真正的价值,并帮助说服不情愿的开发人员(或经理)认为这是一条值得追求的道路。

连续构建服务器是必须的。人们必须记住手动运行以获得其好处的测试套件意味着您正在浪费其大部分好处。