单元测试的投资回报率有确凿的证据吗?

Posted

技术标签:

【中文标题】单元测试的投资回报率有确凿的证据吗?【英文标题】:Is there hard evidence of the ROI of unit testing? 【发布时间】:2010-09-19 05:11:48 【问题描述】:

单元测试对我来说听起来很棒,但我不确定我是否应该花时间真正学习它,除非我能说服其他人认为它具有重要价值。我必须说服其他程序员,更重要的是,说服管理中的 bean-counters,所有花在学习测试框架、编写测试、更新测试等的额外时间都会为自己付出代价,然后是一些。

有什么证据?有没有人真的用两个独立的团队开发过相同的软件,一个使用单元测试,另一个不使用,并比较结果?我对此表示怀疑。我是否应该用“在互联网上查找,每个人都在谈论它,所以它一定是正确的做法”来证明它的合理性?

哪些确凿的证据可以让外行相信单元测试是值得的?

【问题讨论】:

【参考方案1】:

关于 TDD 的更多信息,而不是严格的单元测试,这里是指向 Nagappan、E. Michael Maximilien、Thirumalesh Bhat 和 Laurie Williams 的 Realizing quality improvement through test driven development: results and experiences of four industrial teams 论文的链接。由 Microsoft Empirical Software Engineering and Measurement (ESM) 小组发表的论文,已在此处提及。

团队发现,TDD 团队生成的代码(就缺陷密度而言)比非 TDD 团队好 60% 到 90%。 但是 TDD 团队完成项目的时间要长 15% 到 35%。

【讨论】:

【参考方案2】:

为这些答案添加更多信息,有两个元分析资源可能有助于弄清楚生产力和质量对学术和行业背景的影响:

客座编辑简介:TDD——无畏编程的艺术 [link]

所有研究人员似乎都同意 TDD 鼓励更好地专注于任务 和测试覆盖率。更多测试的事实并不一定 意味着软件质量会更好,但增加的 尽管如此,程序员对测试设计的关注还是令人鼓舞的。要是我们 将测试视为对大量潜在人群进行抽样 行为,更多的测试意味着更彻底的样本。在某种程度上 每个测试都可以发现一个其他测试都无法解决的重要问题 发现,这些测试很有用,特别是如果您可以廉价运行它们。

表 1. 选定的测试驱动实证研究总结 发展:行业参与者*

表 2. TDD 实证研究的摘要:学术 参与者*

测试驱动开发对外部质量和生产力的影响:元分析 [link]

摘要:

本文对 27 项研究进行了系统的荟萃分析, 调查测试驱动开发 (TDD) 对外部环境的影响 代码质量和生产力。

结果表明,总体而言,TDD 对质量的积极影响很小,但对生产力的影响很小甚至没有明显影响。然而,亚组分析 发现质量提高和生产率下降都是 与学术研究相比,工业研究的规模要大得多。 在研究中发现了更大的生产力下降,其中 TDD 和对照组之间的测试工作量差异 过程很重要。质量也有较大提升 在学术研究中发现,当测试努力的差异是 重大的;但是,无法得出关于 由于缺乏数据而进行的工业研究。

最后,影响 开发人员经验和任务规模作为调节变量是 进行了调查,并且具有统计学上显着的正相关性 发现任务规模和改进幅度之间的关系 质量。

【讨论】:

【参考方案3】:

如果您也对反对单元测试的证据感兴趣,这里有一篇经过深入研究和深思熟虑的文章:

Why Most Unit Testing is Waste By James O Coplien (lean and agile guru)

【讨论】:

【参考方案4】:

是的。这是 NCST 的 Boby George 和 Laurie Williams 的一项研究的 link 和 Nagappan 等人的 another。我敢肯定还有更多。威廉姆斯博士publications 进行测试可能会为找到它们提供一个很好的起点。

[编辑] 上述两篇论文专门引用了 TDD,并显示采用 TDD 后初始开发时间增加了 15-35%,但预发布缺陷减少了 40-90%。如果看不到全文,建议使用Google Scholar,看看能不能找到公开的版本。

【讨论】:

第一项研究将敏捷+TDD 与瀑布项目进行比较,如果将两个敏捷团队进行比较,其结果会更加相关。第二项研究提到了其他研究,这些研究几乎没有发现 TDD 项目的质量奖励。而且,当您比较管理层对 TDD 所需额外时间的估计时,具有高领域专业知识的两个团队的估计要高得多,但他们的测试覆盖率也低 20%。这证实了我自己的经验,我发现在我还没有使用过的系统中,保证更为重要,而测试是其他一切的障碍。 这两项研究均未将可比较的过程模型与仅测试方法学变化进行比较。那就是花在UT上的时间实际上更好地花在了例如。系统测试。就目前而言,它也可能是“如果我们更聪明地测试是否有帮助”研究。 如果修复发布后的错误的成本是总开发的 0.01% 怎么办?在这种情况下,TDD 将是一项糟糕的投资。如果错误很少?没有上下文,这些 %s 毫无意义。公平地说,我还没有阅读整个研究。但就目前而言,您的帖子很有用(良好的链接),但没有回答有关投资回报率的问题,IMO。 @Instine 幸运的是(?)有充分的证据表明情况并非如此。修复发布后的错误比在开发早期发现的错误(这是 TDD 所做的)要昂贵得多。在这种情况下,所有发布后错误的总开发成本的 0.01% 似乎不太可能。 (有关详细信息,请参阅 Code Complete,尤其是 Boehm & al.,“Understanding and Controlling Software Costs”,IEEE Trans Softw Eng (1988)。 可能值得注意的是,第一项研究的样本量为 24 名程序员(结对工作,因此 12 个团队)。我不确定统计上有效的样本量是多少,但这些似乎很低。也许其他人知道?【参考方案5】:

我确实有一组数据点 - 来自单元测试的经验。

很多个月前,我是一名刚毕业的学生,​​正在从事一个大型 VB6 项目,并且有机会编写大量存储过程代码。在我编写的子系统中,它约占整个代码库的 1/4——大约 50K 代码中的 13,000 LOC。

我为存储过程编写了一组单元测试,但是如果没有像 Rational Robot 这样的工具,对 VB6 UI 代码进行单元测试是不可行的;至少不是那个时候。

QA 对这件作品的统计是,整个子系统大约有 40 或 50 个缺陷出现,其中 两个 来自存储过程。这是每 6,500 行代码有一个缺陷,而整个代码中每 1,000-1,200 行有 1 个缺陷。还要记住,大约 2/3 的 VB6 代码是用于错误处理和日志记录的样板代码,在所有过程中都是相同的。

无需过多手动操作,您就可以将缺陷率至少提高一个数量级归因于单元测试。

【讨论】:

【参考方案6】:

这是一本关于一个人从内部改变公司的精彩而有趣的读物。它不仅限于 TDD。 http://jamesshore.com/Change-Diary/请注意,他已经有一段时间没有说服“bean counter”,而是采取了“游击战术”。

【讨论】:

链接看起来很有趣...值得一试:改变组织工作流程...【参考方案7】:

有统计数据表明,修复单元/集成测试中发现的错误比在实时系统上修复的成本要低很多倍(它们基于对数千个现实生活项目的监控)。

编辑:例如,正如所指出的,“Code Complete”一书报告了此类研究(第 20.3 段,“质量技术的相对有效性”)。但咨询领域的私人研究也证明了这一点。

【讨论】:

这在 Steve McConnell 的 Code Complete 中有所介绍,这是一本您可能出于其他原因想要放在书架上的书。 这与测试方法无关,而是与在过程中报告错误的时间有关,并且进一步将时间花在寻找规范中的错误上会更好,因为在开发时发现它们时修复它们的成本是据报道,价格高达 1000 倍(每个开发阶段的 10 倍) OTOH,如果您只修复人们在现实生活中实际遇到的问题,您最终可能需要修复的错误要少得多。我也不清楚早期修复错误是否真的更便宜,因为检测规范中的错误可能比检测实现中的相同错误需要更多的努力,并且检测错误是错误修复成本的一部分。这是每个人都相信的事情之一,因为它听起来不言而喻,但我从未见过显示效果的可靠研究。【参考方案8】:

" 我必须说服其他程序员,更重要的是,说服管理中的 bean-counters,所有花费在学习测试框架、编写测试、更新测试等的额外时间都将收回成本,并且然后一些。”

为什么?

为什么不只是安静而谨慎地去做。您不必一次完成所有操作。你可以分小块做。

框架学习只需要很少的时间。

只写一个测试,只需要很少的时间。

如果没有单元测试,您所拥有的只是对您的软件有一定的信心。通过一次单元测试,您仍然有信心,并证明至少通过了一项测试。

仅此而已。没有人需要知道你在做什么。去做吧。

【讨论】:

bean 计数器无法将单元测试与其余代码区分开来,如果它们的生命依赖于它的话。我支持这样做的建议。不过,有一个警告:如果您并不孤单,您需要您的开发人员同事接受这种做法。否则,他们会无意中破坏您的测试。 做吧,不要告诉他们,在茶歇的时候把这个想法卖给你的大学;-) 因为如果你一直没有按时完成任务就会被解雇? @Neko:单元测试不会增加“一点开销”。他们通过防止大量愚蠢的错误来减少整体工作量。工作没有增长;它只是从本质上从糟糕的代码转变为好的单元测试和好的代码。 bean 计数器希望他们的工程师为域问题提供合理的解决方案。您可以只编写测试作为解决方案的一部分。他们甚至不会注意到。如果他们问你,你可以告诉他们你正在花更多的时间来确保它是健壮的并且不需要返工。如果您建议向他们编写单元测试,您就是在征求他们对他们一无所知的事情的批准。【参考方案9】:

嗯,有些大公司要求你使用单元测试,但如果你是小公司,为什么要模仿大公司呢?

多年前我开始进行单元测试时(今天我们主要使用behavior 模型)是因为我无法在一个应用程序中控制所有路径。

我习惯于首先编程和 REPL,所以当我获得单元测试(每个函数一个测试)时,就像将 REPL 带回了非常容易编译的语言。 它给我写的每一行代码带来了乐趣。 我觉得上帝。 我喜欢它。 我不需要报告来告诉我我开始更快地编写更好的代码。 我的老板不需要报告就能注意到,因为我们在做疯狂的事情时突然从未错过最后期限。 我的老板不需要报告就可以注意到“普通”错误的数量从(很多)下降到几乎为零,因为编写非生产性代码这种非常奇怪的事情。

正如另一位发帖人已经写的那样,您不使用 TDD 来测试(验证)。您编写它来捕获规范,即您的单元(对象、模块、函数、类、服务器、集群)工作的行为。

在许多公司中,切换到不同的软件开发模式有很多失败和成功的案例。

每当我有新东西要写时,我就开始使用它。 有句老话对我来说翻译成英文有点困难,但是:

从简单的事情开始 你没有注意到你这样做了。 马拉松训练时,从步行 9 米开始,然后跑 1 米,重复。

【讨论】:

所以,我应该这样做吗?保证能用,别人跟我做也没关系? 其实这是一个 Joel 测试:joelonsoftware.com/articles/fog0000000043.html。在我看来,您可能遇到的问题不仅仅是缺乏关于单元测试的诺贝尔奖研究【参考方案10】:

我对此采取了不同的方法:

您有什么保证您的代码是正确的?或者当您的团队中有人更改 func1() 时,它不会破坏假设 X?如果没有单元测试让你保持“诚实”,我不确定你是否有足够的把握。

保持测试更新的概念很有趣。测试本身不需要经常改变。与生产代码相比,我得到了 3 倍的测试代码,并且测试代码的更改非常 很少。然而,正是它让我晚上睡得香,让我告诉客户我有信心在不破坏系统的情况下实现 Y 功能。

也许在学术界有证据,但我从来没有在商业世界的任何地方工作过,任何人都愿意为这样的测试付费。但是,我可以告诉你,它对我来说效果很好,很快就习惯了测试框架,编写测试让我真正考虑我的需求和设计,远远超过我在不编写测试的团队工作时曾经这样做过。

这就是它为自己付出代价的地方:1)您对自己的代码充满信心,2)您比其他方式更早地发现问题。您不会让 QA 人员说“嘿,您没有费心检查 xyz() 函数的边界,是吗?没有找到那个错误,因为 一个月前找到的。这对他有好处,对你有好处,对公司有好处,对客户也有好处。

显然这是轶事,但它对我产生了奇迹。不确定我能否为您提供电子表格,但我的客户很满意,这就是最终目标。

【讨论】:

我的 QA 人员非常敏锐,但他没有看代码,但很容易看出边界没有检查。 完全同意单元测试迫使您更多地考虑您的设计和正确性,而不是鲁莽地编写代码 客户不付钱给我们写测试。再说一次,他们也不付钱给我们写代码。他们付钱给我们解决他们的问题,我敢打赌,他们也希望问题得到解决。鉴于证据,令人难以置信的是,客户不想保护他们的投资。【参考方案11】:

我们已经用确凿的证据证明,没有单元测试也可以编写糟糕的软件。我相信甚至有证据表明单元测试是糟糕的软件。但这不是重点。

单元测试或测试驱动开发 (TDD) 是一种设计技术,而不是测试技术。编写测试驱动的代码看起来与非测试驱动的代码完全不同。

尽管这不是您的问题,但我想知道这是否真的是解决可能被问错的问题(并带来可能会受到其他报告质疑的证据)的最简单方法。即使您为自己的案件找到了确凿的证据 - 其他人也可能找到反对的确凿证据。

决定技术人员应该如何工作是否是 bean counter 的业务?他们是否在所有情况下都提供最便宜的工具,因为他们认为您不需要更昂贵的工具?

这个论点要么基于信任(敏捷团队的基本价值观之一)获胜,要么基于获胜方的角色权力而失败。即使 TDD 支持者基于角色权力获胜,我也会将其视为失败。

【讨论】:

听,听 :) TDD 的许多确凿证据也来自经验丰富的团队,没有它,他们已经取得了不错的成绩。 TDD 只是改进了他们的结果,而不是凭空创造出来。真正的投资回报率是聘请体面的编码人员并让他们决定如何做事。 “决定技术人员应该如何工作是豆类计数器的事情吗?” --> 所有的商业决策都归结为金钱。不过,很好的答案,+1 @jcollum 但是你如何执行你的工作与金钱无关,如果你希望穹顶一个负责,你让他们决定他们如何做你要求他们做的事情 TDD 不是一种设计技术,它只是一种编码技术。 blog.ploeh.dk/2010/12/22/TheTDDApostate 许多评论者不同意 TDD 涉及重构(这是一种设计技术),但重构并不意味着 TDD。无需测试即可重构,大型复杂重构无论如何都会影响单元测试,即测试也需要重构,因此也可能变为无效/假绿色;更简单的重构很多不会影响测试,但出错的风险更低——因为重构很简单。 @KolA 好吧,考虑到这个答案 10.5 年后,我今天可能会说得更有防御性,但仍然:我不认为 TDD 是 唯一的 i> 您将永远需要的设计技术,Mark 以它是一种很好的 设计技术开场,然后得出结论说它根本不是一种设计技术。我会削弱他的观点,并说它绝不能唯一的设计技术。 我曾经编写过的 TDD 代码 看起来都与我没有编写过的代码不同。我称之为设计的结果。除了 TDD,我最擅长使用白板、讨论和其他工具。但是感谢您的链接

以上是关于单元测试的投资回报率有确凿的证据吗?的主要内容,如果未能解决你的问题,请参考以下文章

单元测试--结队

软件工程实验一 复利计算——单元测试

selenium自动化测试学习1

如何对带有异步的流进行单元测试

严格捕获测试用例以进行单元测试

为什么要做单元测试