将单元测试添加到遗留代码

时间:2009-10-09 02:51:27

标签: unit-testing legacy-code

事实上,你有没有在遗留代码中添加单元测试?代码有多复杂,存根和模拟一切有多难?最终结果值得吗?

8 个答案:

答案 0 :(得分:54)

我发现,最好的方法是逐步添加单元测试,而不仅仅是跳入并说我们现在将对应用程序进行单元测试。

因此,如果您要触摸代码,修复错误或重构,那么首先编写单元测试。对于错误,单元测试将有助于证明问题所在,因为您可以复制它。

如果重构,你会想要编写单元测试,但是你可能会发现测试是不可能编写的,所以你可能需要找到一个高级别,调用将被重构的函数,并对该部分进行单元测试。然后,当您重构攻击性函数时,请编写测试,以确保它按预期运行。

没有简单的方法可以做到这一点。

这个问题可能有助于提出更多建议。 How do you introduce unit testing into a large, legacy (C/C++) codebase?

答案 1 :(得分:37)

Michael Feathers一书“有效地使用遗留代码”是一本涵盖此主题的完整书籍。迈克尔表示,为遗留代码引入测试通常太困难,因为它的结构不可测试。我从书中得到的最多的是一些名为“Sprout functions”和“Sprout classes”的模式。 sprout函数是封装您需要在代码中进行的更改的函数。然后,您只能单独测试这些功能。 sprout类是相同的想法,除了新功能包含在类中。

答案 2 :(得分:8)

是的,这通常很痛苦。我经常最终不得不编写集成测试。

这本书The Art of Unit Testing对此有一些很好的建议。它还推荐了这本书Working Effectively with Legacy Code;我还没有读过后者,但它已经在我的堆栈上了。

编辑:但是,即使是最小的代码覆盖率也是值得的。它为重构代码给了我信心和安全网。

编辑:我确实阅读了“有效使用旧版代码”,这非常棒。

答案 3 :(得分:6)

另请参阅遗留代码单元测试领域的新方法 - Asis project,它受ApprovalTests项目启发并分享其关键概念。

如前所述this article中的ApprovalTests方法:

  

通常你有一个巨大的遗留代码项目,你没有测试   所有,但您必须更改代码以实现新功能,或   重构。遗留代码的有趣之处在于 - 它有效!它   无论如何写,多年都有效。这是一个非常伟大的   该代码的优点。通过批准,您只需一次测试即可获得   所有可能的输出(HTML,XML,JSON,SQL或其他任何输出   be)并批准,因为你知道 - 它有效!完成后   这样的测试并批准了结果,你真的更安全了   重构,因为现在你被锁定了#34;所有现有行为。

Asis工具正是通过自动创建和运行特征测试来保留遗留代码。

有关详细信息,请参阅

答案 4 :(得分:5)

在有效使用遗留代码时引入的单元测试的一种替代方法是characterization tests。这些测试我得到了有趣的结果。当您从点测试时(比称为接缝),它们比单元测试更容易设置。缺点是当测试失败时,您对问题的位置的暗示较少,因为测试区域可能比单元测试大得多。记录有助于此。


xUnit系列的单元测试框架可用于编写特性测试。

在这样的测试中,在事实之后写入,断言验证代码的当前行为。与单元测试不同,它们不能证明代码是正确的,它们只是固定(表征)代码的当前行为。

该过程与TDD类似:

  • 为部分代码编写测试
  • 执行 - 失败
  • 根据观察到的代码行为
  • 修复测试
  • 执行 - 传递
  • 重复

如果修改代码的外部行为,测试将失败。代码的外部行为?听起来很熟悉 ?是的,我们在这里。现在你可以重构代码了。

显然,风险取决于特性测试的覆盖范围。

答案 5 :(得分:5)

查看免费的开源单元测试实用程序库ApprovalTests。如果您是.NET开发人员,创建者Llewellyn Falco已经series of videos展示了他如何使用ApprovalTests来改进新旧代码的单元测试。

答案 6 :(得分:4)

如果您计划重构遗留代码,则必须创建这些单元测试。不要担心模拟或存根 - 担心测试系统的输入和输出,以便您的更改或重构工作不会破坏当前的功能。

我不会骗你,将单元测试改进遗留代码很困难 - 但这是值得的。

答案 7 :(得分:1)

前段时间我一直在谈论关于XPDays遗留代码中反向测试金字塔的想法http://xpdays.com.ua/archive/xp-days-ukraine-2012/materials/legacy-code/

本演示文稿应该回答这样一个问题:为什么在使用遗留代码时有时从集成/功能甚至高级验收测试开始这么重要。然后慢慢地,逐步引入单元测试。没有代码示例 - 抱歉,但您可以在Michaels Feathers一书中找到“使用遗留代码有效工作”中的大量示例。

您还可以查看旧版代码撤退http://www.jbrains.ca/legacy-code-retreat并查找您所在地区的会议。