写点什么

是时候说再见了,Enzyme.js

Piotr Staniów

  • 2021-07-21
  • 本文字数:5120 字

    阅读完需:约 17 分钟

是时候说再见了,Enzyme.js

是时候弃用 Enzyme.js 了


当然这只是一种观点,并非事实,但我认为整个 React 生态系统和社区踏出这一步后都会变得更好。

 

2019 年,我在 AWS CloudWatch UI 团队工作时,是引入 React Testing Library 的幕后推手。那时我经常热情地倡导大家用它来取代 Enzyme。让人们提起兴趣去学习(又一个!)做同样事情的新 JavaScript 库当然绝非易事。但当我离开亚马逊时,我觉得这一运动是很成功的,并且 RTL 在我团队的项目中越来越受到关注。

 

全世界使用 React 的公司还有很多,他们也会因为放弃 Enzyme 而受益匪浅!在这篇文章里,我们就来诚实地讨论一下 React 世界在过去 5 年中发生了怎样的变化,以及为什么 Enzyme 应该被弃用。


本文最初发布于 Piotr Staniow 博客,经原作者授权由 InfoQ 中文站翻译并分享。

弃用在软件开发中意味着什么?


在编程语境中,弃用(deprecation)意味着向其他开发人员传达这样一种观点,那就是某个软件不再是首选解决方案,并且它已被更新的代码所取代。

 

这并不是说你就应该立即停止手头的所有工作,赶快去重写代码来用上更新的软件,也不代表那些已弃用的软件肯定不会再得到维护了。

 

相比之下,弃用表达的是我们希望逐渐有机地过渡到更新的解决方案上这一意图,因为我们认为新方案可以带来更好的用户或开发体验。

 

如今,市面上有两个用于测试 React 组件的库在相互竞争:EnzymeReact Testing Library,我想说服你的是不要在你的新代码中继续使用 Enzyme 了。

React 的一些历史


我们来快速回顾一下过去 5 年 React 世界中发生的事情。

 

2016 年,AirBnB 首次发布了 Enzyme——这是他们自己的 React 测试库。当时,AirBnB 是 React 生态系统的领导者之一,为众多开源项目做出了重大贡献。对于许多人来说,他们做的各种工具已成为行业的事实标准,当然也惠及了无数开发人员。他们还通过流行的 ESLint AirBnB 预设影响了开发人员的代码风格,重新定义了编写现代 JavaScript 代码的意义。

 

如果没有 Enzyme,我很难想象那个时候的测试会是怎么编写的。即使有了 Enzyme,那时候的测试也比现在写起来困难许多。我仍然清楚地记得在我的项目中安装和配置 Mocha、Chai、Sinon 和 JSDOM 的经历,它们加起来才能和今天的一个库——Jest——提供差不多的工具链,问题后者还是开箱即用的,且添加了许多额外特性。

 

世界一直在前进。2018 年 4 月(哇,已经 3 年了?!),Kent C.Dodds 在他的博客上宣布了 React Testing Library 的发布,这彻底改变了在 React 中编写单元测试的方法。

 

2019 年 2 月,React 团队发布了期待已久的新版本 React(16.8),该版本大幅改变了 API 并引入了 React Hooks。实际上,这完全改变了现代 React 代码的编写方式,生态系统中无数的库都被重写或修改以支持 Hooks。

 

我们都改变了自己对基于函数的组件的看法,以前我们认为它们只是无状态和纯表示形式的,现在则把它们看作是基于类组件的完全成熟的替代品。许多 React 教程在那一刻也就此过时了。

 

2020 年 2 月,AirBnB 宣布他们将 Enzyme 的所有权转移到了一个外部 GitHub 组织。虽然他们承诺继续支持 Enzyme,但他们也提到React Testing Library 在他们的项目中越来越受欢迎:


虽然 React Testing Library 等替代选项在 Airbnb 中获得了更多关注,但在可预见的未来,我们仍将继续使用 Enzyme 并为之做出贡献。


快进到 2021 年,目前只有一名开发人员在维护 Enzyme:


澄清一下,我是仅存的 enzyme 开发者。——Jordan Harband


背后要做的事情还有很多——React 团队已经承诺完全重写 React 文档,让它得到应得的更新。新文档还将反映现代 React 代码今天的样貌,这是一个带有 hooks 的函数式组件统治的世界。


类组件在未来几年内还会有一席之地——例如,Facebook 已经有数以万计的类组件处于生产环境。但我们确实建议使用函数式组件和 Hooks 来构建新的应用,所以我们要把这些文档放在最显眼的地方。使用类组件的人们还是能使用它们的文档,并且类组件本身可能有一天也会被分拆到他们自己的包中——但如果确实发生了这种事情,我们将提供迁移脚本来自动化这种迁移过程:)

——Rachel Nabor 的评论

为什么 Enzyme 应该被弃用?


原因很多,大体上可以概括为几个要点:

 

  1. 它长期以来一直落后于 React 的前进步伐,因此在阻碍人们过渡到更新的 React 版本

  2. 它依赖于 React 的内部实现,React 团队不鼓励使用它

  3. 它目前只由一个人维护——对于这么多使用它的公司来说,只依靠一个人来维护他们的一个关键软件是有风险的

  4. 它助长了一些糟糕的测试实践,并且 Enzyme 中的测试无法代表客户体验

  5. 市面上有了一个更好的解决方案,这个行业已经在前进了

不支持新的 React 特性


根据我的经验,在过去的 3 年里,几乎每次都是 Enzyme 不支持 React 的最新特性,而且几个月都跟不上趟。

 

如果你正在编写新代码,我认为你最好使用较新版本的库,因为它们通常会获得更好的支持并符合行业标准。

 

看看 Enzyme 的问题跟踪器你就会发现,它仍然不能完全支持大约 3 年前发布的 React 16。

 

对 React 17 的支持也是近一年来的一个开放问题,你只能在 6 个试图为 Enzyme 提供 React 17 支持的非官方适配器中做出选择,每个适配器都解决了自己的一部分问题,也有自己的一些麻烦。

 

提醒一下,React 18 Alpha 最近发布了——虽然一切都可能发生变化,但它很可能会在几个月后就正式发布。

 

Enzyme 的一个弱点是,Enzyme 中实际上有一些 API 只适用于基于类的组件,并且它们没有基于函数的等效组件。

 

现实情况是,如果你今天正在编写新代码,你可能不希望使用 Enzyme 来测试它。如果你正在编写现代 React 代码,用 Enzyme 的话很有可能你迟早会遇到问题(比如这个这个问题)。到头来,你要么做一些修补来解决问题,要么更改测试场景以匹配这个库的功能限制,要么留下未经测试的代码段。

React 核心团队不鼓励这样做


这个论点不一定会引起你的共鸣,但对我来说,React 背后的专家不鼓励使用 Enzyme,并建议改用 React Testing Library,这一点是很重要的。

 

毕竟,我们都相信他们对 React 实现的计划,以及他们塑造 React API 的方式。所以当他们推荐使用 React Testing Library 时,他们应该是有着充分理由的。

 

有许多迹象表明整个行业已经在向前发展。似乎 Facebook——React 的诞生地——已经冻结了他们的 Enzyme 测试并禁止在任何新测试中使用它:


虽然与这个问题无关,但我认为值得注意的是,如果你可以使用像 React Testing Library 这样不依赖于 React 内部组件的项目,往往会是一个好主意。在 FB,我们冻结了 Enzyme 测试,只保留在因为这个原因不会升级的旧版本 React 上,我们禁止在任何新测试中使用它。我不想偏题到其他话题上,但对于那些因此感到麻烦的人们,我想表示一些鼓励,告诉大家换一种方法是一项值得去做的投资。——Dan Abramov 的评论


再看看今天官方 React 文档中的内容,他们实际上建议你使用 React Testing Library。当然,在某些情况下你是无法使用 RTL 的,我也清楚。培训开发人员学习新技术肯定会增加成本,这会产生一些摩擦。你可能也不会花费数百个开发小时来重写你的那些久经实战考验的测试,毕竟这可能会给它们带来错误。

 

这样也很好!并不需要急着改变,毕竟这不是什么安全问题。

 

不过,我认为这是一条重要的信息——React 背后的专家和社区已经评估了各种选项并做出了选择。如果你不想深入研究为什么 RTL 比 Enzyme 更好,那么你应该先去看看官方文档来了解相关知识。

它只由一个人维护


时至今日,Enzyme 只剩下一个人维护了——他就是Jordan Harband。他是一位多产的开源贡献者,是 TC39 委员会的成员(他们定义 JavaScript),并且是一位真正的英雄,他独自维护着这款为全球数百万个测试套件提供支持的工具。

 

但现实是,他大概需要把时间分配在许多项目上,而且他和我们所有人一样有自己的个人生活。指望一个人可以很好地维护 Enzyme 这样对开发人员的工作如此核心的东西,让他自己处理我们遇到的所有小麻烦和边缘情况,显然是不合情理的。

 

事实上,任何公司将如此多的责任放在一个人身上都是危险的。即使在今天,我们也看到了这种情况的副作用:有些测试没有编写,有些案例需要花几个小时来调试错误,或者我们没有使用有些特性来简化代码库,仅仅因为 Enzyme 没能跟上时代。另一个角度来看,我们可能不应该对任何人施加如此大的责任和压力。

 

问题本质上来说当然是更复杂的,我们应该问一下为什么在使用 Enzyme 的数千家公司中,真正为它的开源代码做出贡献的公司如此之少。要知道这些开源代码是为他们带来收入的啊。我认为现实情况不会很快改变,我们必须应对目前这种远非理想的处境。今天,Enzyme 只有一位开发人员在维护,而且就算它有了更多维护者,解决 Enzyme 的所有问题也需要几个月的时间。

某种程度上更容易误用


在我见过的所有用 Enzyme 和 React Testing Library 编写的单元测试中,我认为误用 Enzyme 比 RTL 更容易。

 

它们代表了两种不同的方法,其中 Enzyme 为组件提供了一些包装器,而 RTL 专注于以“客户看到它们的方式”(DOM 表示)来渲染组件。

 

可能是因为这些年我在 Enzyme 上看到的测试比较多,不管怎样我看到了太多无意义测试的例子。比如一个测试使用一个 spy 函数作为 prop 浅渲染一个组件,接下来使用 Enzyme 的.props()方法提取这个 prop,直接调用它并断言它要被调用。

 

这有意义吗?我是觉得它毫无意义,但类似的事情还是发生了,我认为 Enzyme 让大家太容易通过这种测试创建空行覆盖率了。

 

我更经常看到的是组件 props 的快照,它完全没有说明测试用例的意图,并且将测试与内部实现细节紧密耦合起来。

 

虽然使用 React Testing Library 也肯定有很多方法可以走偏,但根据我的经验,RTL 是一款出色的软件,可以让人们编写更有意义的测试。

这个行业已经在前进了


React Testing Library 在“其他人将如何使用这个库?”和“它鼓励我采用哪些实践?”方面考虑得非常周到。我更喜欢这种方法,而不是 Enzyme 的那种——虽然后者非常强大,但同时也留下了太多实现同一目标的不同方法。

 

一个例子是 RTL 专注于测试客户体验——毕竟,这才是真正重要的。我们的客户不会看到我们的组件有什么 props,或者它们是数组还是对象,客户只关心它是否正常工作——并且会帮助你在未来交付价值。

 

React Testing Library API 也是如此,它提供了查询函数,让你可以使用可访问性特性获取 DOM 元素。这是引入那些特性的一个很好的桥梁,这些特性可以支持你的站点上大约 10%可能需要它们的用户。

 

用 RTL 编写这样的测试也比那些基于浏览器的测试更便宜,因为它们很少出现不稳定状况,而且更容易维护。同时,你正在操作的是非常强大的原生 DOM 元素(好吧,是这些元素的 jsdom 实现)。它不需要你学习任何额外的 API,只用那些我们都知道的原生浏览器 API 就行。

 

如果你正在思考该如何拆分你的测试,我鼓励你在 React Testing Library 中编写尽可能多的测试。如果某些东西不能在 RTL 中测试(比如通过拖放在 SVG 中绘制一个矩形!),那就回退到 Puppeteer 或 Cypress——例如当你需要计算实际样式,或制作一些端到端测试的时候。

 

如果 RTL 不支持某些内容,你还可以使用整个 DOM。不幸的是,如果底层元素来自函数式组件,Enzyme 是不会让你获取的,而是会引发错误

 

不管怎样,整个行业已经在向前发展了。Enzyme 过去一年的每周下载量稳定在 2.1-2.5M 左右。与此同时,React Testing Library 的每周下载量从 180 万次增加到超过 400 万次。


Enzyme 每周下载

React Testing Library 每周下载

 

在 2020 年的 JS 状态调查中,开发人员发表了他们对 React Testing Library 的看法——在那些听说过它的人群中:

 

  • 58%的开发者已经使用并会使用它,

  • 另有 30%的人听说过并愿意使用它。

 

最后,GitHub Insights 工具提供了有关两者使用情况的有趣统计数据。在撰写本文时,在 GitHub 上托管的开源存储库中:

 

  • 354,059 个存储库依赖 Enzyme

  • 2,440,909 个存储库依赖 React Testing Library

接下来呢?


现在看来,整个业界似乎已经转向 React Testing Library 了,这是有很多很好的理由的。

 

很难说 Enzyme 在不久的将来是不是有哪一天就会被弃用了,但这似乎是一个不可避免的结局,可能已经开始倒计时了。虽然今天还有许多人在使用 Enzyme,但我预计这一数字很快就会急剧减少。

 

今天就弃用这个库将帮助许多公司避免引入不必要的技术债务,并向整个社区发出明确的信息,那就是 React Testing Library 才是未来。

 

这不是说“立即停止使用它”,也不是说“立即重写所有测试”。但是,你可能不应该使用 Enzyme 测试来覆盖新编写的代码。这两个库可以安全地共存,你可以简单地禁止使用 Enzyme 来测试新代码,让开发人员有机地逐步过渡过去。

 

React 的未来在于基于函数的组件、React Hooks、异步渲染——而这些特性今天最好搭配 React Testing Library 使用。纵观 Enzyme 过去三年的发展历程,它似乎不太可能赶上所有这些特性,同时还能解决其他那么多问题。

 

现在是时候弃用 Enzyme 了

 

英文原文链接:https://www.piotrstaniow.pl/goodbye-enzyme

2021-07-21 10:004157

评论

发布
暂无评论
发现更多内容

福利贴|这是一个程序员不看一定会后悔的问题

Zilliz

非结构化数据 Milvus Zilliz 向量数据库

Python 中的数字类型与转换技巧

小万哥

Python 程序员 软件 后端 开发

rabbitMQ到底是个啥东西?

程序员万金游

Java 开发 #java Rabbit MQ

华为3场重磅主题演讲先睹为快,顶级云原生&开源盛会即刻出发

华为云开源

华为 开源 云原生 KubeCON

彻底告别传统FTP,新的替代FTP产品比你想象的好的多

镭速

传输协议 FTP传输替代方案

OpenHarmony自定义组件介绍

OpenHarmony开发者

OpenHarmony

开启 Kerberos 安全认证的大数据环境中如何正确指定 HS2 的 jdbc url 地址?

明哥的IT随笔

大数据 hive kerberos

上新啦!腾讯云云原生数据湖产品DLC 2.2.5版本发布,来看特性详解

腾讯云大数据

数据湖

IoTDB 在国际数据库性能测试排行榜中位居第一?测试环境复现与流程详解第一弹!

Apache IoTDB

IPQ9574 IPQ9554 QCN9274 QCN6274 WIFI7 SolutionUnlocking the Potential of Wi-Fi 7

wallyslilly

ipq9554 qcn9274 qcn6274 ipq9574

Generative AI 新世界 | 扩散模型原理的代码实践之采样篇

亚马逊云科技 (Amazon Web Services)

机器学习 #人工智能 生成式人工智能 Amazon SageMaker 大语言模型

WorkPlus私有化部署IM即时通讯平台,构建高效安全的局域网办公环境

BeeWorks

WorkPlus Meet 视频会议,自主可控,支持私有化部署

BeeWorks

企业内部通讯,WorkPlus助您打造高效沟通平台

BeeWorks

使用Optional优雅避免空指针异常

Java随想录

Java 异常

为什么要使用zookeeper

Jerry Tse

zookeeper 分布式锁 分布式系统 共识算法 数据强一致性

跨网传输文件时,如何通过日志记录来审计追溯?

镭速

跨网文件传输

活动预告 | 中国数据库联盟(ACDU)中国行第三站定档成都,邀您探讨数据库前沿技术

墨天轮

MySQL 数据库 oracle postgresql zabbix

华为阅读“鲁迅专栏”已上线,读国内名家作品就上华为阅读

最新动态

Redis类型(Type)与编码(Encoding)

Java随想录

redis

TinyEngine 低代码引擎到底是什么?

英勇无比的消炎药

开源 前端 低代码

ICCV 2023|小红书 4 篇入选论文亮点解读,「开集视频目标分割」获得 Oral

小红书技术REDtech

算法 ICCV

Github上线即遭狂转!上百人通过这份算法手抄本成功上岸字节

程序员万金游

#java java 架构 #算法 #数据结构 #java编程

Redis内存碎片:深度解析与优化策略

Java随想录

Java redis

用友系列之 YonBuilder 低代码平台概论和基本使用

YonBuilder低代码开发平台

低代码 可视化

HarmonyOS使用多线程并发能力开发

HarmonyOS开发者

HarmonyOS

从技术创新到应用实践,百度智能云发起大模型平台应用开发挑战赛!

不叫猫先生

百度智能云 千帆大模型平台

Java训练营毕业总结

jjn0703

火山引擎边缘云:数智化项目管理助力下的业务增长引擎

火山引擎边缘云

数字化 飞书 数智化 #项目管理

华为智慧屏,吹尽狂沙始到金

脑极体

AI智慧屏

如何访问TDH中Inceptor 底层的元数据库TxSQL

明哥的IT随笔

大数据 hive

是时候说再见了,Enzyme.js_语言 & 开发_InfoQ精选文章