是否有软件工程原理将生产系统上的重用和回归测试成本联系起来?


12

我曾为一家负责退休金和投资银行的大型金融交易系统工作。经过15年的功能更改,手动回归测试成本已攀升至每个版本20万美元。(1000万本金,每天交易1000万美元)。该系统还与公司周围的其他19个系统对接,可移动大量数据。该系统是用Java实现的。

但是,我们观察到的是,我们做的“重用”越多,回归测试的成本就越高。(原因是您需要“测试您触摸过的代码”-并且重用/共享的代码在触摸时会影响多个地方。因此尽管“干-不要重复自己”-即不要复制和粘贴代码-我们注意到复制和粘贴代码的经济动机。这是为了降低回归测试的成本,因为我们不想修改可以共享的代码,因为这会带来很大的回归测试影响。

我的问题是,是否存在描述重复使用和回归测试成本之间关系的软件工程原理?

我问这个问题的原因是,将系统分解成要测试的较小部分可以说具有成本优势。

假设:

  1. “回归测试”指的是“验收测试”,即另一个小组花时间代表企业针对系统编写新的测试和重用旧的测试,包括环境和数据设置。

  2. 我知道对大型回归测试成本的下意识反应是“更多自动化测试”。这是一个好原则。在这种环境下,存在两个挑战。

    (a)自动化测试在系统边界上的用处不大,除非该系统也具有很高的自动化测试覆盖率。(势力范围挑战)。

    (b)从文化上讲,当您的系统已经很大且很复杂时,很难在程序员的时间上获得动力,或者在高度自动化的测试覆盖率上进行资本投资。

    (c)维护自动化测试的成本隐藏在项目中,因此很容易在项目级别将其丢弃。

    (d)这只是在银行工作的文化现实。

    (e)我正在以不同的方式(分解)解决此问题。


2
您随随便便地说:“ 我们观察到[…]我们做的'重用越多,[接受]测试成本就越高 ” –您可以对此进行扩展吗?例如,验收测试是否不应该与诸如继承层次结构之类的实现细节无关,而是在使用场景中发挥作用?
阿蒙2013年

2
您的问题很有趣,但是它包含一些非常有偏差的假设,例如“重用是OO的结果”或提到的@amon部分。我建议您完全删除“ OO”部分,因为您的核心问题与编程语言或任何OO编程无关。您还不清楚要记住哪种“重用”-“重用”是一个广义术语,复制粘贴重用不同于组件或库的重用。
布朗

谢谢,这很有帮助。我删除了对OO的引用-并扩展了触摸共享代码(或将成为共享代码的代码)的想法。
鹰眼2013年

1
在当前形式下,我想我只会回答您的问题“不,我不这么认为”,我想这对您来说不是很令人满意。还是您对建立具有自己制造的可重复使用组件的大型系统时真正降低测试成本的原理和实践感兴趣?
布朗

Answers:


11

我们不想修改可以共享的代码,因为这将对回归测试产生重大影响

以上听起来对我有好处。代码越重要,共享的内容就越多,质量要求也就越高,因此更改代码时就应该涉及更多的质量保证

由于您的系统是用Java实现的,因此可以在Java标准库(JDK)中看到上面的示例。它的主要版本很少,并且伴随着非常耗时的测试。甚至很小的发行版都通过非常全面的JCK测试套件运行,以验证是否没有回归。

您可能会认为这以某种方式扼杀了共享代码的演变,而且...是的,这是正确的。与代码更改相关的影响和风险越多,您应该做得越仔细,就需要花费更多的精力来测试其版本。

理想情况下,广泛共享的代码的发布质量应使其根本不需要进行大的更改(不经常进行的增强除外)。约书亚·布洛赫(Joshua Bloch)的一句名言反映了这一思想:

像钻石一样的公共API永远存在。您有机会把它做好,所以请尽力而为。


有了上面所说的内容,您似乎描述的一些问题是由于共享代码开发策略效率低下引起的。特别是,对于重用的代码,仅考虑两个选项显得特别麻烦:要么重复此代码,要么立即将其包含在“核心”共享库中。

仅限于这两个选项是不必要的,同样,您可以找到一些示例,说明如何在使用的JDK中更好地完成此操作。看一下java.util.concurrent软件包(JSR 166)-在Java 5发行之前,它们是一个单独的库,不是核心JDK发行版的一部分。

想一想,这是您忽略的第三个选项,而且相当实用,是在“共享”新共享代码时需要考虑的一个选项。当您仅想一些可以在2-3个组件之间共享的代码时,没有什么迫使您立即将其包含在系统的核心API中。

您可以将此“未成熟”的共享代码打包并发布为单独的库,就像对Java并发实用程序所做的一样。这种方式使您无需进行全面回归测试,因为您只能使用相对少量的相关组件。因此,您还有更多的余地来修改和改进此共享代码并测试其在生产中的工作方式。

库成熟并稳定到足以使您确信其进一步更改的可能性不大之后,您可以考虑将其包含在系统的核心库中,就像并发实用程序最终已包含在JDK中一样。


同样,可以在JDK中找到更改大量重用代码可能涉及多少工作量(包括测试)的具体示例。在版本7u6中,他们更改String了涉及substring性能变化的内部表示形式。Reddit的功能开发人员的评论概述了此更改涉及的工作量:

初步分析来自2007年的GC小组。

在内部,Oracle性能团队维护着一组具有代表性的重要应用程序和基准,用于评估性能变化。这组应用程序对于评估对子字符串的更改至关重要。我们密切关注了性能变化和占地面积变化。不可避免的是,与任何重大更改一样,某些应用程序存在退步,而其他应用程序则有所增长。我们调查了回归分析,以查看性能是否仍然可以接受并保持正确性。

我的答复并非详尽无遗,而是对将近六个月的专门工作的简短总结...


似乎我们两个人都在并行回答一个有很多类似想法的问题……
布朗

@DocBrown是的,有趣的是,我们也几乎同时回答了问题,大约在问题被编辑成表格后一个小时
gnat

9

我认为没有任何指标可以计算“回归测试的成本/构建的重用代码的LOC”。而且我认为没有人会花费太多的时间和金钱来两次构建相同的“大型”系统,一个版本包含许多可重用的组件,而另一个版本则没有对此进行任何认真的研究。

但是我已经看到像以前一样由重用引起的问题,也许您对如何更好地处理此问题感兴趣。

首先,实际上不是重用是您的问题-而是尝试构建自己的可重用组件并在整个系统中使用它们。我确信您会大量使用大型软件包,而不会出现问题:想想您正在使用的整个Java堆栈,或者某些第三方组件(假设您对这些组件感到满意)。但是,与该软件(例如Java库)有什么不同,而您自己的可重用组件却给您带来了如此多的额外回归测试成本?我认为以下几点可能会有所不同:

  • 这些组件非常成熟和稳定

  • 它们是由完全不同的组织独立开发和全面测试的

  • (重新)使用它们,您不必更改它们(实际上,即使您不愿意也不能更改它们,因为您不维护源代码)

  • 您每天不会获得新版本,每年只有一次较小更新(每月最多更新)或间隔较大的更新

  • 大多数更新旨在向下兼容100%,尤其是次要更新

因此,要使您自己的可重用组件更成功,您应该从上面对您的开发进行一些调整:

  • 对于任何可重用的组件,都有明确的责任进行维护,并确保所有重用组件的人员都可以确保在出现问题时立即获得错误修正。

  • 建立严格的版本控制和发布策略。在开发可重用组件时,不要每天都“发布”给每个人(至少,如果这意味着要在系统上运行完整的20万美元回归测试,则不可以)。取而代之的是,只让新版本不时发布,并提供让该组件的用户将更改推迟到新版本的机制。

  • 组件重用的频率越高,提供稳定的接口和向下兼容的行为就越重要。

  • 可重用组件需要非常完整的测试套件来对它们进行隔离测试。

这些事情很多意味着构建组件本身的成本会增加,但也会降低因回归失败而导致的更改成本。


0

尽管由于需要进行更多的测试而导致成本“可观”的增长,但是这种重构类型通常会在将来随着减少系统技术负担而使代码更易于维护。

这有望减少将来的错误,并使新功能或对现有功能的更改更易于实现。

简单地说,我的意思是他们应该花更少的时间,因此花费更少。

在这里,reduce,easy和less都是模糊术语,将来任何节省(或希望节省的费用)都无法计算,因为还没有发生。

较简单的代码库应允许新员工或进入项目的现有员工加快速度,尤其是对于大型系统。

它还可以减少人员流动,因为可以提高现有项目成员的士气。

当然不能保证您会获得这些好处,但是这些都是可以衡量的成本(例如增加的测试)之列,应予以考虑。

实际上,即使由于您的描述而导致最初的增加,更好的代码最终也将最终随着时间的推移降低测试成本。

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.