用自动化测试改造遗留代码的最佳实践


22

我将承担在相对较大和较旧的代码库中重新实现已经定义的接口(一组C ++头文件)的任务。在执行此操作之前,我希望具有尽可能完整的测试范围,以便我可以尽早,轻松地检测到重新实现错误。问题在于,已经存在的代码库没有被设计为易于测试的,具有(非常大的)类和函数,高度的耦合,具有(很多)副作用的函数等。

听说以前有类似任务的经验,以及如何将自动测试(单元,集成,回归等)改造为旧代码的一些好的具体建议,将是很高兴的。


1
步骤1:搜索堆栈溢出。有人问了这个问题。很多很多次
S.Lott

Answers:


20

首先,请阅读并阅读Michael Feathers的《有效地使用旧版代码》 -这是完成此类任务必不可少的帮助。

然后,请注意以下几点:

  • 您对接口有精确的规范/合同,还是实际上仅将现有实现称为“规范”?在前一种情况下,更容易从头开始进行完全重写,而在后一种情况下,则很难甚至不可能。
  • 如果您想重新实现该接口,则花费测试资源的最有用方法是仅针对该接口编写测试。当然,从严格意义上讲,这不符合单元测试的要求,而是功能/验收测试,但我不是纯粹主义者:-)但是,这些测试是可重用的,使您可以直接比较两个实现的结果。
  • 总的来说,除非完全无法维护,我宁愿重构现有代码,而不是从头开始重写。(但是,在这种情况下,您将如何针对它编写单元测试?)请参阅Joel的这篇文章,以获取有关该主题的更详细的讨论。针对该接口创建了一组验收测试,可以为您提供一个薄而有用的安全网,您可以针对该安全网开始谨慎地重构现有代码,使其可以进行单元测试(使用Feathers的书中的想法)。

如果可以的话,我会+3。WELC是必读的书籍,肯定要进行重构……
Johnsyweb 2011年

关于第二点的一个小意见是,对于旧系统,应根据特性测试心态进行测试。也就是说,忠实地捕获软件的当前行为,并且即使根据单元测试的心态,即使某些测试结果看起来很奇怪或不一致,也不要更改行为。(顺便说一句,这个想法也来自WELC的作者。)
rwong 2012年

@rwong,的确如此。没有详细的规范或知识渊博的产品所有者,开发人员无法确定程序的特定行为是否是有意的和必需的,b)是无意的,但现在用户依赖它,c)一个错误, d)到目前为止完全未被发现的错误。在前两种情况下,“修复”它实际上会伤害用户,而在后一种情况下,尽管理论上是正确的,但修复没有任何明显的好处。
彼得Török


2

如果设计是整体的,则在旧代码库上进行复古拟合测试可能会非常困难。

如果可能的话(您有时间/金钱),一种前进的方法是将代码重构为更多可测试的单元。


1

我想添加一个链接。很少有没有那么容易测试的实现重构为更多xUnit友好代码的示例。至于一般方法,请尝试已经提到的链接(Joel post,使用旧版代码

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.