【有效的单元测试】读书笔记第一章 优秀测试的承诺

本文探讨了自动化测试在提升生产力方面的作用,强调了测试不仅仅是质量保证的工具,还是设计代码的一种方式。通过分析测试的思维转变、生产力因素和设计潜力,文章阐述了如何将测试作为设计工具来提高代码质量和效率。重点介绍了测试驱动开发(TDD)和行为驱动开发(BDD),以及如何通过测试驱动设计来驱动代码开发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      开发者应该编写自动化测试,以便发现回归问题时就使构建失败。而且,测试先行的编程风格已有大量的专业研究,使用自动化测试不仅是保护回归,而且是帮助设计,在编写代码之前就指出代码的期望行为,从而在验证实现之前先验证设计。

     问题:自动化测试可以改善生产力,使你获得并保持开发速度。现在自动化测试成为主流,并不意味着测试覆盖率已经达到理想状态,或者生产力无法再改善了。那么测试的价值是什么,测试质量为什么重要?

 1、测试的价值

      (1)有关测试的思维转变

      第一,测试可以帮助我们捕获错误。随着测试的进行,待修复的缺陷的总数不断下降。但是100%的测试覆盖率比95%要好吗?测试越多,额外测试的价值越少。第一个测试最有可能是针对代码最重要的区域,因此带来高价值和高风险。当我们为几乎所有事情编写测试后,那些仍然没有测试覆盖的地方很可能是最不重要和最不可能被破坏的。如下图所示:


     第二,测试帮助我们针对实际使用来塑造设计。假如从调用者的角度来审视代码的设计和行为,用这样的风格:“先写一个失败的测试,然后写足够使测试通过的代码,再写另一个失败的测试。重复这个循环直到完成任务。”

      测试不仅仅是质量保证的工具,或者是对错误及回归的保护。测试作为一种设计代码的方式,提供了具体的目的。编写使失败测试通过的代码比以前的方式简单多了,而且该做的也都做了。通过明确的指出所需的行为,测试帮助我们避免镀金。

      这样我们就在不断认识和理解测试,我们经常因为单元测试有助于避免尴尬、耗时的错误而开始编写他们。随后我们会学到,将测试作为安全网只是等式的一部分,而另一部分---或许是更大部分---其好处是我们将测试表达为思考代码的过程。

     第一种思维导致不能支持双稳态定律:编写测试的最大价值不在于结果,而在于编写过程中的学习。


     第一个稳态表明编写更多更好的测试不再带来额外的价值。第二个稳态进一步爬升,从我们想法的改变中发现更多的回报---将测试认为是最丰富的资源,而不仅仅是验证工具。

     只要测试者认为测试仅仅是质量保证工具,那么潜力就被下面的弧线给限制住了。将我们的认识转变为一种设计工具,能促使我们从质量稳态移动到第二个以测试为设计工具的稳态。

     (2)生产力因素

      为什么要花时间培育你的测试代码、对重复的部分进行重构、普遍的注意它的结构、清晰度和可维护性。

      测试代码天生就比生产代码简单。无论如何,如果你偷工减料,在测试代码的质量上留下技术债务,它将会把你拖慢。本质上,测试代码的重复和多余的复杂性会降低你的生产力,低效测试带来的正面影响。


    对生产力直接影响的是反馈环长度和调试。这两者是消耗程序员时间的罪魁祸首。如果反馈环越长,那么花在调试上的时间就越多。

    bug成本:google估算出程序员在bug出现后马上修复的成本是5美元;在运行整个构建后才发现,修复成本是50美元;在集成测试时发现,修复成本是500美元;到了系统测试阶段,成本高达5000美元。

    等待对变更进行确认和验证在很大程度上牵扯到测试执行的速度。另外三个原因都会影响到程序员的调试量。

    缺乏可读性自然会降低分析速度,鼓励你打开调试器,因为阅读代码不会让你明白,它太难理解。缺乏可读性也会引入更多的缺陷,因为很难看出你造成的错误。而缺陷会导致更多的调试工作。

    缺陷逃逸数量增多的另一个因素是测试结果的准确度。而可信赖性和可靠性都会直接影响测试结果的准确度。为了测试报告的准确性,测试需要断言它的承诺,并以可靠、可重复的方式提供断言。

    通过关注对生产力的影响力,可以扩展质量稳态。使程序员变得高效的关键正是这些已经识别出的根本原因。高产的先决条件是你足够了解你的工具,而不是持续分散你的注意力。一旦你了解了编程语言,你可以浏览其核心API。当你熟悉了问题域,就专注于根本原因--可读性、可靠性、可信赖性和测试的速度。

     (3)设计潜力的曲线

       从编写测试中找到完全不同的价值---价值来自于创新及设计导向,而非防止回归缺陷的保护及验证导向。

       为了能同时达到两个稳态,从而完全发挥测试的潜力,需要:

       第一,像生产代码一样对待你的测试代码--大胆的重构、创建和维护高质量测试。

       第二,开始将测试作为一种设计工具,指导代码针对实际用途进行设计。

2、将测试用于设计工具

       使用自动化测试作为设计工具将世界颠倒过来了,当你用测试设计代码时,将典型的“设计,编码,测试”序列变成“测试,编码,设计”。测试先于编码,并以追溯性的设计活动来得出结论。那结论性的设计活动成为重构,序列变成“测试,编码,重构”。


     (1)测试驱动开发

       TDD,基于一个简单的想法:“在编写出能够证明代码存在的失败测试之前,不写生产代码”。这也是它有时被称为测试先行编程的原因。

      先写测试,会向测试所希望的方向来驱动生产代码的设计。会带来:

      第一,代码变得可用---代码的设计和API适合于你的使用场景。

      第二,代码变得精益---生产代码仅仅实现场景所需要的功能。

      因为,首先将场景翻译为一个可执行的例子,以自动化测试的方式。运行测试,看着它失败,就具有了一个使之通过的清晰目标,只编写足够的生产代码---不要多写。将场景刻画为可执行的测试代码是一种设计行为,测试代码成为生产代码的调用者,使你在还没写任何代码之前就验证你的设计。用具体例子的形式来表达需求时一种强大的验证工具---我们只能通过将测试作为设计工具才能获取价值。

      其次,严格遵循规则,仅仅编写足以使测试通过的代码,会保持设计简单并适合目的。代码质量的罪魁祸首之一,以及使开发者生产力停滞的主要因素,就是称为偶发复杂性。

       测试指出缺陷或代码中缺失的功能,只写足以使测试通过的代码,严格地向简单设计来重构,这三者的组合极其强大,可以将偶发复杂性消灭在萌芽中。这不是魔法药剂,程序员的设计观念和经验会影响到你最终的设计。

      (2)行为驱动开发

       用“行为”来代替“测试”一词。被BDD实践者证明是有效的一个特殊概念,是利用验收测试进行由外而内的开发,先编写一个失败的客户验收测试,用于从客户视角描述系统。编写例子来从业务干系人那里获得反馈,在动手之前就能了解我们是否在构建正确的东西。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值