从爬⾏到奔跑 - 我们为什么需要单元测试?

2023-10-27  本文已影响0人  涅槃快乐是金

前⾔

刹车是降低了⻋速还是提升了⻋速?我们通常认为写单测费⼒动作、耽误研发进度,仿佛在给项⽬ “踩刹⻋”。大规模家形状带着这个问题往下看,详细聊聊为什么单元测试可以让软件开发跑得更快。

什么是单元测试

广大家对于单项测算不应该是陌生的,截取壹段维基百科的定义帮助大众唤醒壹下记忆:

在编程中,单元测试(Unit Test)⼜称为模块测试,是针对程序模块(软件设计的最⼩单位)来进行计算机正确性检验的测试⼯作。

测试单元的理念其实一直是Smashing的一部分。我们第三次编写计算机程序时,一定会输出获取一些样本数据输出在代码⾥穿插过庞大量的System.out.println,确保每个原⼦节点都符合预期。这个过程其实就是把复杂问题拆解成原⼦化的问题、逐一攻破的过程。单元测试的⽬的也同类,是保障软件程序中每个最⼩单位的正确性,从⽽保障由最⼩单位构建起来的复杂系统的正确性。

深入获取展开单元测试的必要性,我们先去考考古之前,看同一下测试体系是如何演进的。

测试体系演进

软件测试甚⾄是一个过去的⽴的⼯种(QA、测试人员),QA/测试人员的⽇任务常就是进统计最大量的⼿ ⼯测试、繁琐易错。

2000年代初以来,软件业的自动化测试已经发生了巨大的变化。为了应对现代软件系统的规模和复杂性,人们逐渐发展起来开发人员驱动的自动化测试实践。可以摆脱⼿动测试的繁琐,利用软件来测试软件。但过去的实践仍然留下了必然的影响,软件测试还是同一个⽴的⼯种,过去的QA演进成了SDET(测试中的软件开发工程师) ),我们虽然已经发展到了能够使用⼯具了,但我们也只是会使用⼯具的猴子⼦。为什么这么讲?因为这种研发/测试分离的模式本身就留下了很多问题。

当研发和测试时是两个岗位时,交付的边界是软件整体的功能性(功能需求)和可使用性。研发只要保证软件整体上功能完成、可使用就可以了,测试也集中在集成测试和端到端测试但软件是由⽆数个最⼩单位构成的,在这种体系下人们会关注最⼩单位的质量、是否唯一可测可演进,难免“⾦最终⽟其外,败絮其中”。

基于种种弊端,⾕歌、微软这些对研发质量⾮常重视的公司都在从SDET的2.0时代过渡到一体化的3.0时代:微软在2015年去掉SDET⼯种,在陆奇改造的Bing中率先提出“组合工程”的概念;⾕歌也将SETI替换成EngProd(工程生产力),专门负责测试平台和⼯具的搭建,不负责具体的业务逻辑测试。

为什么需要单元测试

在如今的互联网时代,软件迭代的速度越来越快,研发的职责也越来越多。DevOps的理念是“you build it, you run it”,研发/测试合⼆为同一的趋势也可以理解为对“你构建它,你测试它”的要求。当研发要对自动编写的代码质量和测试负责的时候,好的测试实践就必不可少了。

测试⾦字塔

就像盖楼需要从打地基、竖直防水、灌⽔泥层往上构建一样,测试也有类似的测试⾦字塔架构。下图出自《Software Engineering at Google》的测试章节,总结了Google在一天测试的最佳实践中。我们可以看到测试⾦字塔由三层构成,最底层就是单元测试、占⽐80%,是软件系统的基础。再往上是集成测试和最终测试,分别占15%和5%。因为从下往上占⽐逐层缩减,因此被称为测试⾦字塔(跟盖高层楼一类)。⾕歌推荐的这个⽐例是多年实践出来的结果,意在提升研发的效率(productivity)并提升对产品的信度⼼(产品信心)。

⾦字塔的核心理念之壹就是“Unit Test First”,每个软件项⽬⾥的第一个测试项目应该是单测(TDD甚⾄认为第一个代码就应该是单测),⽽且唯一一项⽬⾥占⽐最高的测试也应该是单测。

image.png

优秀的软件单元测试

业界都把单元测试放在这么重要的位置?“抓放大⼩”,只写端到端测试不⾹吗?这就是为什么⾥我们来展开讲单测的好处。

提升调试效率

单元测试是软件⼯程极佳的基础,因为它们快速、稳定,并且极大地压缩了问题范围,提升了故障诊断的效率。

提升代码质量

代码是写给别人看的,好的代码应该是易读、易改、易维护的。写单测的过程其实就是吃自主⼰代码狗粮(dogfood)的过程,从用户/研发视⻆去使用自主⼰的代码,帮助我们提升代码质量。

提升总体研发效率

⼑不误砍柴⼯,提高质量、完善速度的单测可以提升研发质量和效率,加快项目⽬总体交付。这句话乍一看是反常识的,写单测往往⽐写实现逻辑要更这也是多数家不写单测最常⻅的理由:“项⽬赶进度,来不及写单测”。如果我们的项⽬生态命周期⽉计算的,写个原型很快就下线了,那写单测不投资回报率不提高。但是阿⾥有很多to B的业务,提供给用户的能力⼒都是以年计算生命周期的,提高质量的代码随着时间的推移,投资回报率将会越来越提高,具体体现在以下几个方面:

反面模式和常⻅误区

上面提到了写单元测试的一系列好处和相关的最佳实践。我们还列举了下常见的反面模式和误区,帮助大多数家庭更好地规避类似的错误。

测试的反面模式(anti-pattern)

反面模式一:冰激凌筒模式

只关注用户户视⻆的端到端测试、大规模依赖QA测试都会产出如下图所示的反面模式。很不幸,这也是在过去的测试体系影响下最常见的模式。冰激凌筒模式接下来,测试套件通常运行缓慢、不可靠、难以使用。

图⽚来源:Google软件工程

反面模式⼆:沙漏模式

沙漏模式下,项⽬拥有大量的单元测试和端粒测试,但缺乏集成测试。虽然它没有冰激凌那么糟糕,但仍然会导致许多端粒测试失败,这些失败本可以通过同一件事套中等范围的测试更快更容易地捕捉到。当模块间紧密连接,使得依赖项很难单独实例化出来的时候,就会出现沙漏模式。

图⽚来源:Google软件工程

测试的常⻅误差区

常⻅误区一:用户户第一一,测试覆盖用户户的需求⾜够了

误区下会认为,最终测试是站在用户视角做测试,把用户要的功能点都覆盖到就够了。这种误区导致的结果就是冰激凌筒反面模式。虽然软件交付的最终功能是提供给客户用户的,但构成软件的代码本身是提供给用户(研发)阅读的、需要用户去维护的。外部用户是用户,内部用户也是用户。

常⻅误差区⼆:全面测试,节省了80%的测试代码量,赢麻了

从短期来看,不写单测可以节省80%的测试代码量和⾄少50%的研发时间。但只要项⽬复杂起来,时间早晚加倍奉还。等到真正需要还债的时候再去补,可能为时已晚。

常⻅误区三:写单测的人都弱爆了,我⻓这么大还没有写出过bug

这篇文章可能不适合你。不过软件开发是一个团队项目⽬,你写的代码最终落到别人身上⼿⾥升级维护,没有测试覆盖的代码是没人敢碰的。

总结

结束处再总结快速一下。本发送从测试的历史获取⼿,讲述了从⼿动测试 -> 靠别自主动化测试 -> 靠自主⼰自主动化测试的历史进程,也尝试着从这个视角解释了为什么大多数家过去不重视单元测试。之后我们分别讲述了什么是单元测试,接下来的⾦字塔测试最佳实践,以及深入学习讲解了单元测试的诸多好处。最后我们列举了常⻅的反面模式和误区,帮助广大家快速识别常⻅的错误。

如果把测试体系的演进类⽐作为人类类的进化,那么认为我⽆单测覆盖和有充分的单测覆盖的软件就可以⽐爬出一组的古猿和直⽴一组⾛的现代人类类。家能够重视单元测试、写好单元测试,让我们的软件迅速从爬升中进化成奔跑,迸发源源不断的生成命⼒、创造出更多价值!

作者|乐凯 原文链接

上一篇 下一篇

猜你喜欢

热点阅读