将单元测试添加到旧代码中


79

事后,您是否曾经将单元测试添加到旧代码中?代码有多复杂,存根和模拟一切有多难?最终结果值得吗?


4
我将检查“有效使用旧版代码”。希望它能给我一些有关如何为所有这些静态依赖项编写包装器的良好指导!
BuckeyeSoftwareGuy 2009年

Answers:


57

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

因此,如果您要触摸代码以进行错误修复或重构,请首先编写单元测试。对于错误,单元测试将帮助您证明问题出在哪里,因为您可以将其复制。

如果进行重构,您将要编写单元测试,但是您可能会发现该测试无法编写,因此您可能需要找到一个高层,调用将要重构的函数,并对该部分进行单元测试。然后,在重构进攻功能时,编写测试,以确保其正常运行。

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

这个问题可能会提供更多建议。 如何将单元测试引入大型的(C / C ++)代码库中?


8
+1用于逐步添加测试。
TrueWill

42

迈克尔·费瑟斯(Michael Feathers)的书“有效地使用旧版代码”是一本涵盖该主题的整本书。Michael指出,为遗留代码引入测试通常太难了,因为它的结构无法测试。我从书中得到最多的是几个名为“ Sprout函数”和“ Sprout类”的模式。发芽函数是一种封装您需要在代码中进行的更改的函数。然后,仅对这些功能进行单元测试。除了新的功能包含在一个类中之外,萌芽类是相同的想法。


10

是的,而且通常很痛苦。我经常不得不不得不编写集成测试。

这本书《单元测试的艺术》对此有一些很好的建议。它还建议该书有效地使用遗留代码;我还没有读过后者,但是它在我的书架上。

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

编辑:我确实读过《有效使用旧版代码》,它很棒。


4
为“有效地使用旧版代码” +1:充满了很好的建议;实际上,即使在未开发的环境中,也值得阅读,就像构建可测试性代码方面的宝贵资源一样。
itowlson

1
+1表示使用集成测试替换单元测试的想法。通过适当的嘲弄,前者通常足够好
DVK

7

还要看看遗留代码单元测试领域中的新方法-Asis项目,它受ApprovalTests项目的启发,并共享其关键概念。

随着对ApprovalTests提到在接近这篇文章

通常,您有一个庞大的旧代码项目,根本没有测试,但是您必须更改代码以实现新功能或重构。关于遗留代码的有趣之处在于-它可以工作!无论如何编写,它都能工作多年。这是该代码的一大优势。有了批准,只需进行一项测试,您就可以获取所有可能的输出(HTML,XML,JSON,SQL或可能的任何输出)并批准,因为您知道-它可以工作!在完成了这样的测试并批准了结果之后,通过重构,您实际上会更加安全,因为现在您可以“锁定”所有现有行为。

Asis工具正是关于通过自动创建和运行表征测试来保留旧代码的方法。

有关更多信息,请参见


如何没有更多的赞誉?如果回购按其声明的方式进行,则应为选择的答案。
lolololol ol'May

顺便说一句,它处理功能的副作用吗?甚至有可能解决这个问题?
lolololol ol'May

5

表征测试也是有效使用遗留代码中引入的单元测试的一种替代方法。通过这些测试,我得到了有趣的结果。从点进行测试比进行单元测试(称为接缝)要容易,因此它们比单元测试更容易设置。缺点是,当测试失败时,您对问题所在的提示会更少,因为被测试的区域可能比单元测试大得多。日志记录在这里有帮助。


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

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

该过程类似于TDD的过程:

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

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

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



4

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

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


我开始为一直在处理的旧代码创建单元测试。但是,我意识到我一直在编写集成测试,而不是单元测试,因为我创建了实际数据并将其插入数据库中。我看不到为该遗留代码创建纯模拟和存根的方法,因为它根本不是为测试而构造的。
Vin Shahrdar,2017年

1

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

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.