(接受)测试驱动开发的相对成本效率


15

我想知道资源计划对软件项目的总体影响是什么,项目的需求和设计是由自动验收测试和单元测试驱动的,而不是软件开发的“传统”方法。

在此处输入图片说明

根据您的经验,与采用更多“传统”开发方法相比,在TDD下完成软件项目对资源需求的总体影响是什么?在我看来,质量会提高,不确定性会减少,这是因为测试要早完成,但是要求提前进行测试似乎需要更多开发人员时间才能完成。由于预先消除了错误,开发工作量增加了多少,或者实际上减少了多少?

客户需要多少努力?他们是否必须改变与项目相关的方式,特别是如果它们习惯于预先进行大型设计?客户总体所需的小时数是否增加了,或者实际上减少了?

我可以想象,在TDD项目开始时(因为没有软件开发计划),在TDD迭代过程中时间估计将非常模糊。例如,是否有20%的项目能使信心增加到足以最终为客户提供或多或少的稳定时间和金钱估算?

注意:我不是在这里寻找主观意见或理论,所以请不要spec测。我正在寻找更多有关TDD的真实经验。


我确定没有现实世界的数据。您只能基于peoeple的实际经验获得主观意见和理论。
欣快感

1
@Euphoric:我正在寻找基于现实世界经验的客观观察和现实。抱歉,我不清楚。但是,我不需要硬数字。我会接受这样的一般印象:“虽然我们的开发时间确实增加了,但是维护成本却下降了,因为软件更可靠,客户更好地理解了软件,因为他们参与了整个开发工作。”
罗伯特·哈维,

2
那么,这是基于观点的问题吗?这当然听起来像一个
BЈовић


@BЈовић:参见我的问题正文的最后一段。
罗伯特·哈维

Answers:


11

首先要说明的是,TDD 不一定能提高软件的质量(从用户的角度来看)。这不是灵丹妙药。这不是万能药。减少错误的数量并不是我们进行TDD的原因。

进行TDD主要是因为它可以产生更好的代码。更具体地说,TDD导致代码更易于更改

是否要使用TDD取决于您的项目目标。这将是一个短期咨询项目吗?上线后是否需要支持该项目?这是一个微不足道的项目吗?在这些情况下,增加的开销可能不值得。

但是,根据我的经验,TDD的价值主张随着项目中所涉及的时间和资源的线性增长而呈指数增长。

好的单元测试具有以下优点:

  1. 单元测试警告开发人员意外的副作用。
  2. 单元测试允许在旧的,成熟的系统上快速开发新功能。
  3. 单元测试使新开发人员可以更快,更准确地了解代码。

TDD的副作用可能是较少的错误,但是不幸的是,根据我的经验,大多数错误(尤其是最讨厌的错误)通常是由不清楚或较差的要求引起的,或者不一定在第一轮单元测试中涵盖。

总结一下:

版本1上的开发可能会比较慢。2-10版的开发将更快。


1
我喜欢“更好的代码”的明确并置与增加“软件的质量”不同,即程序员在代码中所重视的东西并不一定能满足客户的要求。

1
前期验收测试和单元测试不是用来阐明要求的吗?
罗伯特·哈维,

@RobertHarvey他们应该不一定。单元测试和验收测试将反映开发人员在编写要求时的理解。当他们开始编写软件时,开发人员可能有从完全了解到不了解需求的任何内容。等式的这一部分更多地取决于客户和产品经理。从理论上讲,测试应该会有所帮助。实际上,“取决于”。
Stephen

1
我需要澄清的是,我们在这里是在单独讨论TDD,而不是结合TDD的SCRUM实现。孤立地讲,TDD的全部目的在于编写测试,以便您编写更好的代码并可以在以后更快更安全地进行重构。
Stephen

1
@Stephen:也许我应该更清楚地说我在谈论TDD的风格,它把接受测试作为需求收集过程的一部分。我已在问题中添加了图形以使其更加清晰。
罗伯特·哈维

6

关于测试驱动开发的软件制造”中有一章,其中引用了本文讨论的文章。

案例研究由Microsoft的三个开发团队和采用TDD的IBM的一个开发团队进行。案例研究的结果表明,相对于未使用TDD做法的类似项目,四种产品的预发布缺陷密度降低了40%至90%。从主观上讲,采用TDD后,团队的初始开发时间增加了15–35%。

当然,这些结果是否可以推广到您的情况是显而易见的,TDD的支持者会提出质疑,而TDD的反对者会提出质疑。


4
该研究的问题在于,他们在适应TDD之前没有对代码进行单元测试。TDD是不是一个神奇的工具,它由40-90%的缺陷数量减少通过简单地采用它
BЈовић

1
@BЈовић我不认为他们在该论文的任何地方都声称“不可思议”。他们声称有些团队采用了TDD,有些团队则没有,他们得到了“类似”的工作,并且记录了一些缺陷密度和开发时间。如果他们强迫非TDD团队以任何方式编写单元测试,以便每个人都进行单元测试,那么这将不是生态有效的研究。

具有生态学意义的研究?Sorta取决于您要测量的内容。如果你想知道是否编写测试前面的问题,那么每个人都必须编写单元测试,而不仅仅是TDD组。
罗伯特·哈维

1
@robert Harvey这是混淆变量的问题,而不是生态有效性。设计一个好的实验需要逐渐减少那些。例如,如果对照组在事后编写单元测试,则人们会认为该实验不合理,因为对照组的工作方式是在野外发现的。

2
幸运的是我没有说过。

5

我没有任何研究论文或统计数据可以提供给您,但是我将结合我在一个团队/组织中的工作经验,这些团队/组织历史上的单元测试覆盖率低至平均水平,并且没有端到端测试,并且逐步通过更多的ATDD(但具有讽刺意味的是,不是传统的TDD)方法将标准移到我们现在的位置。

具体来说,这是项目时间表过去如何发挥作用(并仍然在同一组织中的其他团队/产品上发挥作用)的方式:

  • 长达4周的分析和实施
  • 2周的回归测试,错误修复,稳定和发布准备
  • 修复已知缺陷1-2周
  • 2-3周的代码清理和后期制作问题/支持(未知缺陷/计划外停机)

这似乎是荒谬的开销,但它实际上是很常见的,在许多组织中,常常由于缺少或无效的质量检查而被掩盖。我们拥有优秀的测试人员和严格的测试文化,因此这些问题要尽早发现并提前解决(大部分时间),而不是在许多月/年的过程中慢慢解决。55-65%的维护开销是较低的比花在调试的时间80%的普遍接受的标准-这似乎是合理的,因为我们确实有一些单元测试和跨职能团队(包括QA)。

在我们团队最新产品的第一版发布期间,我们已经开始对验收测试进行改造,但还远远不够,我们仍然不得不依靠大量的手动测试。这次发布比其他版本的痛苦要小一些,这部分是因为IMO的偶然性验收测试,部分是因为相对于其他项目,我们的单元测试覆盖率非常高。不过,我们在回归/稳定化上花费了将近2周,在后期制作问题上花费了2周。

相比之下,该初始发行版以来的每个发行版都具有早期接受标准和接受测试,而我们当前的迭代如下所示:

  • 8天的分析和实施
  • 2天稳定
  • 0-2天的后期制作支持和清理

换句话说,我们将维护费用从55-65%提升到20-30%。相同的团队,相同的产品,主要区别在于验收测试的逐步改进和简化。

每个sprint的维护成本,对于QA分析人员来说是3-5天,对于开发人员来说是1-2天。我们的团队有4个开发人员和2个QA分析人员,因此(不计算UX,项目管理等),最多60个工作日中有7个工作日,而我将凑整15%的实施开销安全的一面。

我们在每个发布期间花费15%的时间来开发自动验收测试,并且在此过程中,我们可以削减70%的每个发布以进行回归测试并修复生产前和生产后的错误。

您可能已经注意到,第二个时间轴比第一个时间轴更精确,也更短。预先接受标准和接受测试使之成为可能,因为它极大地简化了“完成的定义”,并使我们对发布的稳定性更有信心。到目前为止,没有其他团队在两周一次的发布时间表上取得成功,除非进行相当琐碎的维护发布(仅修正错误等)。

另一个有趣的副作用是,我们已经能够根据业务需求调整发布时间表。一次,我们不得不将其延长至大约3个星期,以与另一个版本保持一致,并且能够在提供更多功能的同时做到这一点,而无需花费任何额外的时间进行测试或稳定化。另一时间,由于假期和资源冲突,我们不得不将其缩短到大约1.5周。我们不得不进行较少的开发工作,但是,正如预期的那样,能够花更少的时间进行测试和稳定化而又不会引入任何新的缺陷。

因此,以我的经验来看,验收测试(尤其是在项目或冲刺的早期完成时,以及由产品负责人编写的验收准则进行良好维护时)是您可以做出的最佳投资之一。不同于传统的TDD,这是其他人正确指出的是更专注于创建可测试比代码无缺陷的代码- ATDD确实有助于抓住缺陷很多速度更快; 这在组织上相当于每天都有一支测试人员大军进行完整的回归测试,但价格却便宜得多。

ATDD是否会帮助您进行以RUP或(ugh)Waterfall风格完成的,持续3个月或更长时间的项目?我认为陪审团仍未解决。以我的经验,长期运行的项目中最大和最丑陋的风险是不切实际的期限和不断变化的需求。不切实际的截止日期将导致人们采用快捷方式,包括测试快捷方式,并且对需求的重大更改可能会使大量测试无效,从而要求重写它们并可能增加实施开销。

我非常确定,ATDD对于敏捷模型或非正式敏捷但发布时间表非常频繁的团队来说,将带来可观的回报。我从未在一个长期项目中尝试过它,主要是因为我从未去过或什至没有一个组织愿意在这种项目中尝试过它,因此请在此处插入标准的免责声明。YMMV等。

PS在我们的情况下,“客户”不需要额外的精力,但是我们有专门的全职产品负责人,他实际上在编写接受标准。如果您从事“咨询软件”业务,我怀疑让最终用户编写有用的验收标准可能会困难得多。产品负责人/产品经理似乎是进行ATDD的基本要素,尽管我只能根据自己的经验再说一次,但我从未听说过ATDD在没有人履行职责的情况下会成功地实践。


这非常有用,谢谢。在我看来,ATTD可能不会改变TDD工作的性质,但这确实是有道理的,尤其是当您听说有人能够按时且按预算开发出编写良好,相对无错误的软件而又无需必须广泛利用单元测试。
罗伯特·哈维

@RobertHarvey:我应该澄清-我们仍在创建单元测试,只是不作为TDD过程的一部分。通常,验收测试首先进行或与初始开发并行进行,然后完成代码,然后进行单元测试和重构。有时我认为TDD可以帮助某些开发人员编写更好的代码,但是我还不能支持。尽管我可以自己说-我经常在编写单元测试的过程中在自己的代码中发现很多错误和设计缺陷。
Aaronaught

1

资源需求

根据您的经验,与使用更多“传统”开发方法相比,对在TDD下完成软件项目的资源要求的总体影响是什么?

以我的经验,通过预先定义明确的验收标准,然后写测试,可以立即减轻要求进行前期测试的成本。我不仅发现前期测试的成本得以降低,而且还发现它通常可以加快总体开发速度。尽管这些速度的提高可能会因项目定义不佳或需求变更而消失。但是,我们仍然能够很好地应对这些变化,而不会造成严重影响。在以下情况下,ATDD还可以通过其自动测试套件大大减少开发人员在验证正确的系统行为方面的工作:

  • 大型重构
  • 平台/软件包升级
  • 平台迁移
  • 工具链升级

这是假设一个团队熟悉所涉及的过程和实践。

客户参与

客户需要多少努力?

他们必须不断参与。我已经看到前期投资大幅度减少,但仍存在大量需求。我没有衡量,但我可以肯定的是,这对客户来说是一笔较大的时间投资。

但是,我发现经过5个左右的演示后,他们看到他们的软件逐渐成形,客户关系得到了极大的改善。随着人与人之间的融洽关系发展,客户对时间的承诺随着时间的流逝有所减少。

项目估算

我可以想象,在TDD项目开始时(因为没有软件开发计划),在TDD迭代过程中时间估计将非常模糊。

我发现这通常是一个问题,即问询的定义是否明确以及技术负责人是否能够批准(包括评估)项目。假设项目完好,并且您具有合理的速度平均值和标准偏差,我们发现很容易获得一个不错的估计。显然,项目越大,不确定性就越大,这就是为什么我通常将一个大项目分解成一个小项目,并承诺以后会继续的原因。与客户建立良好的关系后,这样做就容易得多。

例如:

我团队的“冲刺”为期一周,我们有一个运行平均值和标准差。最近14周的偏差。如果项目为120点,我们的平均值为25和标准差。然后估计项目完成的偏差为6:

Project Total / (Mean Velocity - (2 * Std. Deviation) = 95% Time Estimate
120           / (25            - (2 * 6             ) = 9.2 weeks

我们使用2标准。我们的95%置信度估计的偏差经验法则。实际上,我们通常在第一个标准下完成该项目。偏差,但超出我们的平均水平。这通常是由于改进,更改等导致的。


因此,基本上,您的意思是TDD通过鼓励利益相关者去做他们应该做的事情来改善开发工作,例如提供明确,可行的要求和接受标准。
罗伯特·哈维

1
好吧,不仅如此。随着项目的进展,参与度的增加将使开发人员与利益相关者之间的对话更好。它允许开发人员提供诸如成本更低的替代方案之类的东西,因为他们对利益相关者想要的东西的了解会进一步完善。它使利益相关者可以在意识到事情丢失或在没有开发人员的不利回应的情况下无法工作时,可以及早更改需求。并且没有许多通常来自利益相关者的不合理期望。
Dietbuddha 2013年

-1

要求预先进行测试似乎需要更多开发人员时间才能完成。由于预先消除了错误,开发工作量增加了多少,或者实际上减少了多少?

这实际上是不正确的。如果您的开发人员正在编写单元测试(应该这样做),那么时间应该大致相同或更好。我说得更好,因为您的代码将经过完全测试,并且他们仅需编写代码即可满足要求。

开发人员的问题在于,他们倾向于实现甚至不需要使软件尽可能通用的东西。

客户需要多少努力?他们是否必须改变与项目相关的方式,特别是如果它们习惯于预先进行大型设计?客户总体所需的小时数是否增加了,或者实际上减少了?

没关系 满足要求的人都应该做到最好。

如果您采用敏捷的开发方式,那么这并不意味着就需要大的设计。但是,完成的要求,体系结构和设计越好-代码质量将提高,并且完成软件的时间将减少。

因此,如果他们喜欢BDUF,那就让他们这样做。作为开发人员,这将使您的生活更轻松。


1
据我了解,TDD和BDUF通常彼此不兼容。
罗伯特·哈维,

3
BDUF通常与任何良好的开发管理规范都不兼容。但是有可能以TDD方式进行BDUF项目。TDD是一种用于创作质量更高的软件的技术,而BDUF是一种用于引发需求的技术。一项糟糕的技术,但仍然是一项技术。
斯蒂芬·

@RobertHarvey对,但如果他们想做BDUF,这是他们的选择。如果您确实在做敏捷,那么您可以自由地改进他们的设计,并且仍然可以进行TDD。
2013年

所以你说如果我编写单元测试,我的代码将被完全测试,并且如果所有测试通过,那当然意味着该软件没有错误(或至少更好)。因此,我只需要测试软件的每种方法,例如“ function testSqr(){int a = 3; assertTrue(mySqr(a)== 9);} function mySqr(int a){return 9;}”
Dainius

@Dainius不,请重读。100%的代码覆盖率不是错误。是的,您需要对每种方法进行单元测试。当然,单元测试数据库访问,GUI等毫无意义。单元测试不适用于那些。
2013年
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.