跳至主内容

Jest 30:更快、更轻、更好

· 12 分钟阅读
Svyatoslav Zaytsev
Svyatoslav Zaytsev
非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

今天我们很高兴地宣布 Jest 30 正式发布。本次版本包含了大量变更、修复和改进。尽管这是 Jest 有史以来最大的主要版本更新之一,但我们承认一个大版本更新间隔三年确实太长了。未来我们将致力于更频繁地发布主要版本,确保 Jest 在未来十年持续保持卓越。

如果你想跳过所有新闻直接开始,请运行 npm install jest@^30.0.0 并遵循迁移指南:从 Jest 29 升级到 30

有哪些新特性?

Jest 30 速度明显更快,内存占用更少,并带来了大量新功能。首先让我们看看破坏性变更:

破坏性变更

  • Jest 30 停止支持 Node 14、16、19 和 21

  • jest-environment-jsdom 从 jsdom 21 升级到了 26

  • 最低兼容 TypeScript 版本提升至 5.4

  • 移除了多个 expect 别名。eslint-plugin-jest 提供了自动修复工具,可自动升级代码库

  • 不可枚举的对象属性现在默认不会参与 toEqual 等对象匹配器的比较

  • Jest 现已默认支持 .mts.cts 文件

  • --testPathPattern 已重命名为 --testPathPatterns

  • Jest 现在能正确处理先被拒绝后被捕获的 Promise,避免误报测试失败

  • 我们对快照打印功能进行了多项改进,可能需要更新快照。Google 已弃用我们使用的 goo.gl 链接,虽然我们也不喜欢这种变动,但你必须更新所有快照

  • Jest 现在每个包都打包为单个文件,这提升了性能,但如果你开发了访问 Jest 内部机制的工具可能会受影响

以上只是部分重点内容,完整的破坏性变更列表请查阅 更新日志Jest 30 迁移指南

性能与内存优化

通过模块解析、内存使用和测试隔离等关键优化,Jest 30 实现了显著的性能提升。借助全新的 unrs-resolver,模块解析功能变得功能更丰富、更符合标准且速度更快。感谢 @JounQin 完成迁移工作。根据项目不同,你可能会观察到测试运行速度大幅提升且内存占用显著降低。例如某个包含客户端和服务端的大型 TypeScript 应用在其部分代码库中观察到测试运行速度提升 37%,内存使用降低 77%:

Jest 29Jest 30
Server tests~1350s / 7.8 GB max~850s / 1.8 GB max
Client tests~49s / 1.0 GB max~44s / 0.8 GB max

Jest 本身速度很快,但由于其测试隔离机制,运行缓慢的用户代码常常会加剧性能问题。当测试遗留了未关闭的句柄(如未清除的定时器或与其他服务的连接)时,可能导致 Jest 挂起或变慢。Jest 30 在检测和报告这类问题方面表现更佳,帮助开发者更轻松地定位和修复缓慢或有问题的测试。例如 Happo 的测试通过清理未关闭句柄并升级到 Jest 30,运行时间从 14 分钟缩短至 9 分钟,速度提升了 50%。

如果您正在使用将多个模块的导出合并到单个文件的文件(即"桶文件"),我们推荐使用 babel-jest-boostbabel-plugin-transform-barrelsno-barrel-file 等工具,避免为每个测试文件加载大量应用代码。这可将性能提升高达 100 倍。

测试文件之间的全局变量清理

Jest 通过在独立的 VM 上下文 中运行每个测试文件来实现隔离,为每个文件提供全新的全局环境。但如果您的代码未在测试文件后清理全局变量,可能导致内存泄漏并拖慢测试运行。Jest 30 新增了检测功能,会在测试运行后提醒您未正确清理的全局变量。

未来版本中,Jest 将在每次测试运行后自动清理全局变量。如果您在使用 Jest 30 时未收到未清理全局变量的警告,现在即可将清理模式设为 "on" 来完全启用此功能,从而显著节省内存并提升性能:

export default {
testEnvironmentOptions: {
globalsCleanup: 'on',
},
};

Jest 的默认设置为 globalsCleanup: 'soft'。如需禁用此功能可设为 off。若需保护特定全局对象不被清理(如共享工具或缓存),可使用 jest-util 将其标记为受保护:

import {protectProperties} from 'jest-util';

protectProperties(globalThis['my-property']);

感谢 @eyalroth 实现此功能!

新功能

增强的 ECMAScript 模块与 TypeScript 支持

使用 Jest 原生 ESM 时现已支持 import.meta.*file://。此外,您现在可直接使用 TypeScript 编写 Jest 配置文件,且原生支持 .mts.cts 文件而无需额外配置。若使用 Node 原生 TypeScript 类型剥离功能,我们不再加载 TypeScript 转换器剥离类型,从而加快测试运行。

间谍函数与 using 关键字

您现在可将 JavaScript 新的显式资源管理语法 (using) 与 Jest 间谍函数结合使用。如果环境支持,编写 using jest.spyOn(obj, 'method') 会在代码块结束时自动恢复间谍函数,无需手动清理。

test('logs a warning', () => {
using spy = jest.spyOn(console, 'warn');
doSomeThingWarnWorthy();
expect(spy).toHaveBeenCalled();
});

文档

expect.arrayOf

Jest 30 引入了新的非对称匹配器 expect.arrayOf,可验证数组中每个元素是否符合指定条件或类型。例如,您可验证数组所有元素均为数字:

expect(someArray).toEqual(expect.arrayOf(expect.any(Number)));

文档

新的 test.each 占位符:%$

使用 test.each 进行数据驱动测试时,现在可在测试标题中加入特殊占位符 %$ 来插入测试用例的编号。例如:

test.each(cases)('Case %$ works as expected', () => {});

该占位符 %$ 会被替换为测试的序列号。

文档

jest.advanceTimersToNextFrame()

@sinonjs/fake-timers 已升级至 v13,新增了 jest.advanceTimersToNextFrame() 方法。此函数可将所有待处理的 requestAnimationFrame 回调推进到下一帧边界,让您无需猜测毫秒时长即可轻松测试动画或依赖 requestAnimationFrame 的代码。

文档

可配置的测试重试机制

Jest 30 增强了 jest.retryTimes() 功能,新增选项让您能灵活控制重试行为。现在您可以指定重试延迟时间,或在测试失败后立即重试,无需等待整个测试套件完成:

// Retry failed tests up to 3 times, waiting 1 second between attempts:
jest.retryTimes(3, {waitBeforeRetry: 1000});

// Immediately retry without waiting for other tests to finish:
jest.retryTimes(3, {retryImmediately: true});

文档

jest.unstable_unmockModule()

Jest 30 新增实验性 API jest.unstable_unmockModule(),为模块解除模拟提供更精细的控制(尤其在使用原生 ESM 时)。

文档

jest.onGenerateMock(callback)

新增的 onGenerateMock 方法可注册回调函数,该回调会在 Jest 为模块生成模拟时触发。您可以在模拟对象返回测试环境前对其进行修改:

jest.onGenerateMock((modulePath, moduleMock) => {
if (modulePath.includes('Database')) {
moduleMock.connect = jest.fn().mockImplementation(() => {
console.log('Connected to mock DB');
});
}
return moduleMock;
});

文档

其他改进

自定义对象序列化

现在可以在自定义对象上定义静态属性 SERIALIZABLE_PROPERTIES,从而控制快照和错误消息中包含哪些属性,使输出更聚焦关键信息。

文档

异步配置支持

setupFilesAfterEnv 中列出的测试文件现在可导出异步函数或使用顶层 await,功能与 setupFiles 保持一致。

更多改进...

完整变更请参阅 更新日志

已知问题

jsdom 的规范兼容性调整可能导致部分用例失效,尤其是测试中模拟 window.location 的场景。Jest 现提供 @jest/environment-jsdom-abstract 包,方便您基于 jsdom 构建自定义测试环境。若需临时修补 jsdom,可应用jsdom 补丁到你的项目。未来我们可能提供更适配测试场景的 jsdom 替代方案。

未来规划

Jest 作为十年来最受欢迎的 JavaScript 测试框架,支撑着从小型库到全球最大代码库的各类项目。随着时间推移,我们积累了技术债务:部分功能仅少数用户使用,为减少破坏性变更我们长期维持兼容性。有些功能应通过扩展而非核心框架实现,部分特性甚至可能引导错误测试实践。同时核心团队人员变动导致版本迭代放缓。我们将通过以下方式改进:

  • 性能优化/技术债务:精简核心架构,移除非主流功能,聚焦核心价值

  • 稳定发布周期:建立可预测的版本迭代和废弃策略

  • 开放协作:公开开发流程,增加贡献入口,拓展贡献者群体

  • 大胆革新: 作为 Jest 团队,我们应当更加果敢。当前诸多因素制约着 Jest 发挥其全部潜力,是时候采取行动了。

好消息是,自我们构建这个具有清晰关注点分离的模块化框架以来,Jest 始终具备践行这些原则的坚实基础。现在正是付诸实践的时刻。更多细节即将揭晓!

致谢

没有社区的辛勤付出,就没有这次发布。衷心感谢大家!

@SimenB, @mrazauskas, @Connormiha, @liuxingbaoyu, @k-rajat19, @G-Rath, @charpeni, @dubzzz, @stekycz, @yinm, @lencioni, @phawxby, @lukeapage, @robhogan, @fisker, @k-rajat19, @connectdotz, @alesmenzel, @rickhanlonii, @mbelsky, @brunocabral88, @brandon-leapyear, @nicolo-ribaudo, @dj-stormtrooper, @eryue0220

特别向在此版本中首次为 Jest 贡献代码的开发者们致以谢意。感谢你们让 Jest 变得更好,惠及整个社区!

@eyalroth, @KhaledElmorsy, @mohammednumaan, @bensternthal, @BondarenkoAlex, @phryneas, @jayvdb, @brandonchinn178, @latin-1, @rmartine-ias, @fa93hws, @Dunqing, @gustav0d, @noritaka1166, @andreibereczki, @Dreamsorcerer, @satanTime, @icholy, @ecraig12345, @cgm-16, @sebastiancarlos, @dancer1325, @loganrosen, @zakingslayerv22, @dev-intj, @tez3998, @anbnyc, @pengqiseven, @thypon, @co63oc, @danielrentz, @jonasongg, @andrew-the-drawer, @phryneas, @hyperupcall, @tonyd33, @madcapnmckay, @dongwa, @gagan-bhullar-tech, @ikonst, @ZuBB, @jzaefferer, @brandonnorsworthy, @henny1105, @DmitryMakhnev, @askoufis, @RahulARanger, @Jon-Biz, @fynsta, @KonnorRogers, @BondarenkoAlex, @mouadhbb, @kemuridama, @Avi-E-Koenig, @davidroeca, @akwodkiewicz, @mukul-turing, @dnicolson, @colinacassidy, @ofekm97, @haze, @Vadimchesh, @peterdenham, @ShuZhong, @manoraj, @nicolo-ribaudo, @georgekaran, @MathieuFedrigo, @hkdobrev, @Germandrummer92, @CheadleCheadle, @notaphplover, @danbeam, @arescrimson, @yepitschunked, @JimminiKin, @DerTimonius, @vkml, @ginabethrussell, @jeremiah-snee-openx, @WillianAgostini, @casey-lentz, @faizanu94, @someone635, @rafaelrabelos, @RayBrokeSomething, @DaniAcu, @mattkubej, @tr1ckydev, @shresthasurav, @the-ress, @Mutesa-Cedric, @nolddor, @alexreardon, @Peeja, @verycosy, @mknight-atl, @maro1993, @Eric-Tyrrell22

Jest 加入 OpenJS 基金会

· 1 分钟阅读
Ricky Hanlon
Ricky Hanlon
非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

Meta 开源与 OpenJS 基金会横幅图片

今天我们激动地宣布,Jest 正式加入 OpenJS 基金会!

此次变更通过 OpenJS 基金会的 Impact Project 计划,将项目所有权从 Meta 转移至 Jest 核心团队。我们衷心感谢 Meta 创建了 Jest 并多年来的鼎力支持,也热切期待 Jest 成为由社区主导的项目后的未来发展!

更多信息请查看 Meta Engineering 博客OpenJS Foundation 博客的公告。

Jest 28:轻装上阵,兼容性更佳 🫶

· 9 分钟阅读
Simen Bekkhus
Simen Bekkhus
非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

Jest 28 终于来了!它带来了许多开发者期待已久的功能,包括支持在多台机器上分片(sharding)运行测试、package exports支持,以及自定义模拟计时器(fake timers)行为的能力。这些只是部分亮点功能,我们将在本文中详细介绍更多更新。

此外,正如我们在去年的Jest 27博客文章中所预告的,我们已从默认安装中移除了不再默认使用的包。这使得安装体积减少了约三分之一。

Jest 27:Jest 的新默认设置,2021 年版 ⏩

· 8 分钟阅读
Tim Seckinger
Tim Seckinger
非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

在约一年前的 Jest 26 博客文章中,我们宣布经过两个破坏性变更较少的主要版本后,Jest 27 将调整部分开关设置,为新建项目或能平滑迁移的项目提供更优的默认配置。这让我们有机会从 Jest 28 的默认分发包中移除某些依赖,将其改为独立安装的可插拔模块。采用新默认配置的用户可获得更小的安装体积,而需要这些包的用户仍可单独安装它们。

自具有里程碑意义的版本 15 引入 Jest 的新默认设置以来,Jest 27 首次对默认配置进行了重大调整,旨在让 Jest 保持快速、轻量且面向未来的特性。本文将详细解释这些默认配置变更及其他重要破坏性变更,但首先让我们聚焦激动人心的新功能!

Jest 26:滴答作响

· 7 分钟阅读
非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

五年前我们开始重构 Jest 时,目标是打造一个开箱即用的零配置测试运行器:对初学者友好,几乎适用于所有测试场景,并能扩展至大型项目。Jest 15 是关键版本之一,它整合了所有功能,提供了良好的默认配置,让用户无需任何设置即可运行 Jest。但这种做法有个显著缺点:Jest 会安装大量你可能不需要的依赖项到项目中。

现在,我们开始解决这一问题,在保持 Jest 友好性和可扩展性的同时努力减小其安装体积。我们在 Jest 26 中进行了以下重大变更

Jest 25:🚀 为未来奠定基础

· 7 分钟阅读
Simen Bekkhus
Simen Bekkhus
非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

Jest 25 正在为未来的重大变革奠定基础。为此,我们将破坏性变更控制在最低限度,但内部架构调整可能在升级过程中需要特别注意。主要变化包括将 JSDOM 从 v11 升级至 v15、测试运行速度提升 10-15%、新增过期快照的差异视图,以及放弃对 Node 6 的支持。

自 Jest 24.9 以来,已有超过 80 位贡献者提交了 200 多次代码更新。和往常一样,请查看更新日志获取完整的变更列表。

Jest 24:💅 焕然一新、精致优雅且支持 TypeScript

· 10 分钟阅读
Simen Bekkhus
Simen Bekkhus
非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

今天我们很高兴地宣布 Jest 的下一个主要版本——第 24 版!距离上一个次要版本发布已经过去了 4 个月,而距离 Jest 23 的发布更是有 8 个月之久,因此这次升级是一个重大版本,为每个人带来了新功能!亮点包括:通过将 Jest 内部升级至 Babel 7 实现内置 TypeScript 支持,修复了长期存在的控制台输出丢失问题以及计算大型差异时的性能问题,还有一个全新的闪亮官网。✨

完整变更列表请参阅更新日志

支持 Jest 开源

· 3 分钟阅读
Ricky Hanlon
Ricky Hanlon
非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

Jest 由开源贡献者和 Facebook 员工组成的社区共同维护。

我们的开源贡献者代表社区开发新功能、修复错误并维护问题积压。Facebook 员工也进行类似工作,但专注于 Facebook 规模特有的问题,并在发布前通过 Facebook 庞大的测试套件运行所有候选版本。

我们都在为创造愉悦的测试体验贡献力量。

在 Jest 峰会上,我们宣布了 Jest 开放集体(Jest Open Collective)。这是我们支持 Jest 开源社区的方式。需要明确的是:Facebook 员工无法从 Jest 开放集体中获益。 该集体的唯一宗旨是支持 Jest 社区的开源力量。

本文将阐述 Jest 开放集体的性质、组织架构和预期目标。