单元测试怎么就成了银弹?

近几年国内各厂似乎有将单测覆盖率演变成代码质量硬性标准的势头,你当然可以认为这是内卷的另一种体现,因为千行 bug 率、单测覆盖率等是难得的或许可以「量化」代码质量的手段,但我相信推动者或多或少地有将单元测试作为测试领域银弹的思想,本文就分析分析这种思想所存在的问题。

从TDD谈起

TDD 指测试驱动开发,坦白而言,对于大部分业务部门来说这都是一个听起来很高端的词汇,毕竟看到自己项目中那匮乏的测试用例时常人都会产生这样的心理活动。很多人也常常在想,如果我们能实践 TDD ,也许我们的代码开发效率就能更高、代码的正确性保证就能更省心、更可靠了。

然而事与愿违,如果没有老板的首肯,TDD 在大部分业务部门中都是难以落地的。原因很简单,那就是 TDD 会肉眼可见地加长项目上线周期,但收益却只能在中后期才有所体现且难以量化。

如果要落地 TDD ,我们首先需要花费精力去设计和编写测试用例,而在根据用例完成常规开发后,我们还需要根据用例执行的情况对代码进行一定的重构。在这个过程中,第一个流程的工作内容与 QA 的职责是重叠的,也就是会造成 QA 和研发两方面的人力的浪费。而更麻烦的是重构阶段,很多产品的研发时间线是以 MVP 为起点的,公司和 PM 更希望一期工程能够尽快上线以便观察效果,至于代码方面的问题只要不影响核心功能的使用,可以放到后期再逐步优化,所以这样的排期冲突很难以技术合理性为理由去强行解决。

而如果我们把重构妥协到第一期上线之后,那也就意味着 TDD 并没有发挥真正的作用,也就是测试用例仅仅是功能验证手段,并没有驱动开发。其次一期时间紧不代表二期时间宽裕,几次妥协下来,项目代码和测试用例之间的关系已十分错综复杂,实际联系已不再紧密,TDD 很容易就演变为了 DDT ,我称其为开发测试驱动,研发开始根据代码恶补用例,而这样的举措通常收益甚小。

后补的单元测试为什么收益小

首先我们要明白,很多业务在代码层面是缺少测试用例的,最直接的体现就是单元测试少得可怜。当我们试图为这些历史代码补充用例时,我们的出发点常常是通过用例的设计使得某个环节的输入输出能固定满足几种场景的功能要求,这也就意味着这一过程和这些用例具有以下特点:

  1. 为了得到原有逻辑对应的输出,我们需要构造特定的输入来满足需求,这在业务代码的场景中往往会依赖持久层比如 DB 中的数据,即输入不能保证稳定。
  2. 这类用例只能用于当前的历史代码逻辑,当代码逻辑发生调整时用例要协同调整,但由于用例数量根基不牢,调整起来需要一一甄别。
  3. 后补的用例试图保证的是功能的正确性,对代码实现的合理性、架构的合理性都没有帮助。
  4. 补充时常常会假设当前逻辑稳定可靠,故很难发现当前功能中存在的固有问题。

可以看到,补充得来的单元测试没有自主性,必须依附于业务代码的实现逻辑,导致业务代码的修改会导致单元测试的修改,而这类单元测试只能在功能层面为未来的修改提供依据,即未来的修改能跑通之前的用例则代表该功能至少在已知的正确性层面上应该没有发生改变,但对于新逻辑调整所带来的新边界条件及输入输出组合却难以验证,同时这类单元测试本质上与直接通过接口调用并没有太大的差异。

另一方面,对持久层数据的依赖更使得我们所写的单元测试常常还没有直接对接口发起调用来得方便。而如果你想通过模拟数据源的方式固定一套稳定的输入输出,那就意味着你额外维护了一套测试环境,在未来的迭代中很难保证不会与主测试环境和线上的逻辑发生冲突,维护成本陡增。

我们该如何看待单元测试

测试是一门学问甚至科学,单元测试只是众多测试手段中的一种,他有自己适用的场景,如果不能完全以 TDD 的思想开发,那么在适当的场景使用单元测试,再结合使用增量测试、集成测试、回归测试、冒烟测试等其他测试方式来制定系统的测试计划,我们的代码才能尽可能地做到高质量、高合理性。

那么什么场景适合单元测试呢?我认为如果按照 DDD 战术模式的分层思想,则领域层的任何逻辑都适用于单元测试。这无关领域模型充血与否,原因主要在于领域逻辑在合理分层的设计下是与持久层没有直接耦合的,该层的单元测试易于编写和维护。同时它深藏于接口所在的展示层之下,却包含了最根本的业务逻辑,其他测试方式有可能无法完整测试领域层的逻辑,故为其添加单元测试有助于发现隐藏的问题,并能更好地维护代码的健壮性。同时研发只对底层核心业务逻辑进行测试也能避免与 QA 团队的工作内容发生重叠,进而避免了人力的浪费。此外好的领域设计会将领域逻辑在实现时进行更加细致的逻辑拆分,而这恰好符合了 TDD 的基础要求之一,因此对这类逻辑实行 TDD 也会更易于落地。

而对于其他层,他们常常包含多个领域模型的交互,逻辑的执行也依赖 DB 等持久层的数据或仅仅包含其他层的 DTO 转换逻辑,这些逻辑完全可以交由其他测试方式,通过制定科学的测试流程来保证质量。特别的,展示层是产品逻辑和多端交互最直接的体现,所以它是最适合从接口层面根据出入参进行用例设计和实现的,而不应由研发人员使用各种接口 Mock 工具编写复杂的测试代码创造所谓的单元测试。

关于单测覆盖率

回到单测覆盖率,现代业务项目的代码实现尤为复杂,对于 Java 类语言尤甚。笼统地要求提高整个项目的单测覆盖率就意味着研发人员需要花费更多的时间来关注足够简单或不重要的逻辑,而大部分公司的现状又使得单测多为事后补充,效果甚微。

所以我们大可以把用于编写冗余单元测试的时间花费到对于项目真正重要的重构优化上,同时在项目初期就尽量保证核心领域逻辑的单测覆盖率,这样才能在效率和质量之间找到合理的平衡点,为业务发展提供助燃剂。

博客链接:https://easonyang.com/2021/06/15/is-unit-test-a-silver-bullet/

关注公众号「举一得一」获取最新文章更新

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,313评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,369评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,916评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,333评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,425评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,481评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,491评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,268评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,719评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,004评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,179评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,832评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,510评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,153评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,402评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,045评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,071评论 2 352

推荐阅读更多精彩内容

  • 前言 随着Web业务的日益复杂化和多元化,前端开发也有了前端工程化的概念,前端工程化成为目前前端架构中重要的一环,...
    CharmSun阅读 1,217评论 0 1
  • 单元测试 故事场景 工厂生产电视机 工厂首先会将各种电子元器件按照图纸组装在一起构成各个功能电路板,比如供电板、音...
    深度沉迷学习阅读 617评论 0 0
  • 本文主要阐述单元测试(UT)的重要性,以及解释一些常见的困惑,以帮助我们写出质量更高的 UT。至于类似 Mocha...
    玖叁_阅读 5,513评论 0 1
  • 一、为什么要引入单元测试 在开发过程中我们会遇到这样一些问题: 面对需要重构庞大的模块代码时无从下手 修改了一处地...
    茶浅呀阅读 357评论 0 1
  • 首先我们要理解什么是单元测试,集成测试,系统测试,验收测试。这是根据开发的阶段命名的测试方法,其中单元测试是粒度最...
    小小奶狗阅读 2,298评论 0 1