网易首页 > 网易号 > 正文 申请入驻

“TDD 就是死亡”?我要为单元测试辩护

0
分享至

作者 | Guilherme Ferreira

译者 | 马可薇

策划 | 丁晓昀

在 2014 年的时候,David Heinemeier Hansson 在软件开发界引起了轩然大波。他在 RailsConf 的台上公然宣布“TDD 就是死亡”。

这是个大胆的举动,但他也成为了很多不满于测试的人所寻找的领头人。很多人选择了跟随,开发者们就此分成了两个阵营。

当时所掀起的新浪潮一路带我们到了今天,单元测试不再重要,集成测试占据上风。Mike Cohn 所提出的著名测试金字塔如今被重塑为菱形形状。推动这股浪潮的因素并不唯一,在对现有测试实践不满的背后,或许并不难找到许多原因。

这种情况常常伴随固化的实践传播、缺乏的正确指导,以及沉溺的抽象思维出现。人人都试图做到最好,不断尝试、失败,再尝试,直到有人能打破锁链,开拓不同的道路,一条承诺通往低维护性测试套组的道路。

什么是最好的方向?

即使是在新领域,我们也很容易遗忘历史,这是我在这个行业中所学到的事。飞速发展的步伐让我们相信过去没有答案,而未来充满奇迹。我不知道未来会如何,但我相信我们总会倾向于追寻创新而非寻找信息。

或许下面这些问题能让很多质疑用测试菱形替代金字塔的声音:

  • 问题是由单元测试或单元测试编写所引起的吗?

  • 集成测试是否应用于需要的组件?

  • 我的误解是否导致了多处相同的断言?

  • 我是通过测试优化设计,还是围绕现有设计进行测试?

寻 根

答案或许又一次藏在了过去。

那么在集成测试上,历史能告诉我们什么呢?历史中,集成测试是不同开发单元一同测试的阶段。这些单元独立开发,且通常来自不同团队。在这一阶段,我们要确保的是所有接口的实现和运行正常。

如今的集成测试常常用于同一团队所开发的代码单元,这就意味着每个源码文件都是一个系统边界,相当于每个代码文件都是由同一个自主团队开发一样,模糊了单元测试和集成测试之间的界限。

因此,我们可以断定,集成测试与单元测试之间区别的根源是个错误。认定集成测试是用于团队之间测试,而单元测试是用于单一团队测试,这种区分观念本身便是不对的。我们所要解决的果正是自己造下的因。

我们应当明确这二者的界限,明确开发团队之间的界限而非层次。界限的明确会让你从新的角度看待系统的角色,以及它与其他领域的交互。类似于 Alistair Cockburn 所描述的 六边形架构,后者也被称作是“端口与适配器”。在他的描述中,系统拥有里外两个面,而我们要做的,就是通过明确定义的边界来连接这两个面。

这有什么用呢?正是这个内外层的关系,明确了单元测试与集成测试之间的关系。单元测试负责从外向内地测试界限,而集成测试则是从内向外地对边界测试。具体来说,集成测试确保了适配器、网关和客户端,这些负责连接其他开发单元(如 API、插件、、数据库和模块)之间关系的正常运作。

针对行为的测试

“单元测试”中的“单元”是什么?单元是指行为的单元。这段定义中完全没有提到过任何针对单一文件、对象,或者函数的测试。那么,为什么编写针对行为的测试很难?

多数测试类型都会遇到的问题来自软件结构和测试之间的紧密联系,其中开发者忽视了测试目标,并以透明盒(有时也被称作是白盒)的方式应对测试。透明盒测试是指内部设计时以系统正常运作为目标,常见于单元测试。但透明盒的问题在于,测试往往会过于细化导致产生大量用例,而这些用例又与底层结构紧密耦合,给维护增加了难度。

人们对单元测试的不爽部分来源于此。而集成测试由于更多地脱离底层的设计,受重构的影响往往比单元测试要小。

我更倾向于从另一个角度看问题。这一点是集成测试的优势,还是由透明盒测试所带来的问题?如果我们以基于行为的不透明盒(有时也被称作黑盒)方式进行单元测试,那么结果是否一样或更好?

人们常常以为不透明盒测试只能应用于系统的外部边界,但这是不对的。我们的系统是由许多边界组成,有些可以借助通信协议访问,有些可以通过进程中的适配器扩展。这些适配器都有自己的边界,可以通过基于行为的方式进行测试。

模拟:孤注一掷

透明盒测试通常大量使用模拟(mock),可一旦过度依赖模拟,测试便会更难维护。也许这就是 Mark Seemann 所说的“桩(stub)和模拟破坏了封装”。在正视这类由过度使用模拟所带来的问题后,厌恶、甚至不惜一切代价地避免模拟是很正常的。仅使用 API 的测试通常会导致对模拟的过度依赖。

但问题又回到了最初,这是否真的是由模拟或对模拟的误用导致的呢?

模拟和桩或许更难维护,但它们的存在是有意义的。它们让测试更快也更稳定,我们需要掌控它们,且不在必要之外滥用模拟和桩。

减少代码的公共表面

透明盒测试的另一弊端在于其会导致更多代码的暴露。验证器、映射器,以及其他可能的内部实现细节都会因为测试的缘故暴露在公共契约(contract)内。任何使用 Java 或 C# 的人都知道接口在代码库中的普遍程度。仅仅为了模拟一个依赖,开发者很可能会引入一个新接口。

可被从外部访问的代码将会更难变动,测试也将成为必须项,让代码的可维护性受到质疑,在没有大量重写单元测试的情况下,重构几乎成为不可能。乍一看,这一问题似乎利于集成测试;集成测试更关注于外层,不会暴露很多的实现细节。

但还是那个问题,这究竟是单元测试的问题,还是我们在实现单元测试方式的问题?如果我们以不透明盒的形式进行单元测试,无视内部设计方式,仅关注于消费者需求,或许我们会收获更小的契约,一个更易于测试的契约,更少的测试量,以及更便于维护的测试。

以架构为指导原则

测试常常是围绕架构进行的。我们常常在系统设计完成之后才会考虑测试,但这也会让系统测试的难度更上一层楼。多层架构中这种情况屡见不鲜,对数据访问技术的依赖让领域层的单元测试更加繁复。

采用测试隔离的架构可以轻松避免这种问题。无论是六边形架构还是干净架构(Clean Architecture),可选的有很多。这类架构的构建是独立于设备的,所有基础设备依赖都会通过依赖配置接入系统。架构的单元测试会更加舒适,并引导集成测试到适当的应用下:测试连往外部的适配器。

集成测试的适配器会为我们的测试策略带来一个薄弱点。在所有组件相连的情况下进行集成测试,将收获测试在配置和组合方面的优势,显然这是我们想要的目标。当然我们也可以继续在组件全部相连的情况下测试,但这些测试只会是“烟雾弹”,不需要测试所有的边界情况,从而导向更稳定,也更可靠的测试。

结 论

质疑行业中的固有观念很重要,但在质疑之前先充分理解这些观念也同样重要。

我们都知道历史是不断重复的,过去会带给我们关于将来决定的信息。但我们也应该明白同样的错误将会不可避免地一遍遍发生。这是人之本性,是否能规避这些错误将取决于我们自己。测试策略也是这些不断重复的错误之一。我们要面对这些由于信息或知识匮乏,以及错失已有优秀实践而导致的痛点。

测试与架构是息息相关的。我们需要在设计架构时不忘测试情况,在我们追寻优秀测试策略时,单元测试仍会是我们可用的工具。

https://www.infoq.com/articles/unit-tests-testing-pyramid/

个性化测试流程,不搞一刀切 (https://www.infoq.cn/article/l0jqESl4bgNs3jC0GFvG)

只擅长构建软件是不够的,我们必须擅长构建可测试的软件 | QCon(https://www.infoq.cn/article/SxEUUtjMIWxc2cvJGZK4 )

声明:本文为 InfoQ 翻译,未经许可禁止转载。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
鹿晗的日子有多难过?片约基本不复存在了,也没多少综艺敢邀约她

鹿晗的日子有多难过?片约基本不复存在了,也没多少综艺敢邀约她

老佳聊球666
2024-12-01 19:29:22
德国称确认两名破坏“北溪”管道的人员

德国称确认两名破坏“北溪”管道的人员

每日经济新闻
2024-12-01 07:21:03
胡可分享一家人的哈尔滨之旅,大儿子安吉瘦身成功,帅气十足!

胡可分享一家人的哈尔滨之旅,大儿子安吉瘦身成功,帅气十足!

古装影视解说阿凶
2024-12-01 19:32:09
英国情报六局:若俄罗斯总统普京获胜了,中国将权衡其影响

英国情报六局:若俄罗斯总统普京获胜了,中国将权衡其影响

新时光点滴
2024-12-01 08:32:25
特朗普真正恐惧之处 是他让全球都相信他真的说到做到

特朗普真正恐惧之处 是他让全球都相信他真的说到做到

月满大江流
2024-11-30 16:31:19
马苏,身高165厘米,“马漂亮”这称号,真不是盖的。

马苏,身高165厘米,“马漂亮”这称号,真不是盖的。

人情皆文史
2024-11-01 00:11:01
西部排名又乱了:独行侠创NBA奇迹,灰熊冲到第3,湖人掉到第8

西部排名又乱了:独行侠创NBA奇迹,灰熊冲到第3,湖人掉到第8

篮球大视野
2024-12-01 14:18:19
母亲:你舅舅是我的亲弟弟,你应该给他养老,女儿:轮不到我养。

母亲:你舅舅是我的亲弟弟,你应该给他养老,女儿:轮不到我养。

施工员小天哥
2024-12-01 07:24:08
涉案超1.4亿元,后台控制“股票”涨跌!近400人获刑,诈骗集团组织架构首次曝光→

涉案超1.4亿元,后台控制“股票”涨跌!近400人获刑,诈骗集团组织架构首次曝光→

证券时报
2024-12-02 00:04:08
全胜!独行侠少了一个刷子,一个坑,球队变化很大,攻防全面提升

全胜!独行侠少了一个刷子,一个坑,球队变化很大,攻防全面提升

清蒸玉米粒
2024-12-01 19:28:35
重返76人!西蒙斯这该死的运气!骗到养老合同,大帝活该被骂软蛋

重返76人!西蒙斯这该死的运气!骗到养老合同,大帝活该被骂软蛋

张家大院趣说天下事
2024-12-01 09:20:03
利物浦2-0曼城 英超冠军自信心彻底没了 根本原因还是在瓜帅自己

利物浦2-0曼城 英超冠军自信心彻底没了 根本原因还是在瓜帅自己

敖铭
2024-12-02 01:56:36
78岁大爷坦言:住过儿子家和养老院,才明白老了后最好的归宿在哪

78岁大爷坦言:住过儿子家和养老院,才明白老了后最好的归宿在哪

惟来
2024-12-01 07:04:16
伊朗本打算车轮战累死以色列,没想到自己的小弟一个个被锤爆。

伊朗本打算车轮战累死以色列,没想到自己的小弟一个个被锤爆。

小企鹅侃世界
2024-12-02 00:26:32
极氪 009 汽车在香港开启正式交付,郭富城成当地首位星级车主

极氪 009 汽车在香港开启正式交付,郭富城成当地首位星级车主

IT之家
2024-12-01 19:32:24
赖清德开出2条件,否则不允许在台湾举办上海-台北“双城论坛”

赖清德开出2条件,否则不允许在台湾举办上海-台北“双城论坛”

橘色数码
2024-12-01 16:12:35
上海真“霸气”,竟然为了一个公司修建一条地铁,且开通初期运营

上海真“霸气”,竟然为了一个公司修建一条地铁,且开通初期运营

记录生活日常阿蜴
2024-12-01 23:46:21
大批轰炸机升空,美国连夜跑路!北约终于发现,惹了不该惹的人

大批轰炸机升空,美国连夜跑路!北约终于发现,惹了不该惹的人

傲气经说
2024-12-01 16:25:02
刷爆全网,又来一部上头的新剧

刷爆全网,又来一部上头的新剧

美剧院线
2024-11-30 22:39:08
全人群易感,酒精对其无效!官方明确:不得带病上岗(课)

全人群易感,酒精对其无效!官方明确:不得带病上岗(课)

鲁中晨报
2024-12-01 21:32:12
2024-12-02 08:39:00
InfoQ
InfoQ
有内容的技术社区媒体
10454文章数 50948关注度
往期回顾 全部

科技要闻

11月成绩单:小鹏首破3万,蔚来小米破2万

头条要闻

代驾司机闯红灯后 车主的保费上涨930元:为何要我承担

头条要闻

代驾司机闯红灯后 车主的保费上涨930元:为何要我承担

体育要闻

勇士四连败,到底是谁的错?

娱乐要闻

黄晓明姥姥去世,祖孙俩手牵手好温馨

财经要闻

400人获刑!诈骗集团后台控制"股票"涨跌

汽车要闻

科技是中国豪车梦的支点 腾势Z9走心试驾体验

态度原创

教育
艺术
房产
本地
公开课

教育要闻

求向量模值的一道高考数学题,首先一定要求他的平方!

艺术要闻

故宫珍藏的墨迹《十七帖》,比拓本更精良,这才是地道的魏晋写法

房产要闻

一燃再燃!又卖2亿!白鹅潭顶流,引爆全城!

本地新闻

云游中国|来伦布夏果感受充满Passion的人生

公开课

一块玻璃,如何改变人类世界?

无障碍浏览 进入关怀版