跳至主内容

Jest 14.0: React 树快照测试

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

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

Jest 的核心哲学之一是提供集成的"零配置"体验。我们致力于让编写有价值的测试变得尽可能轻松。我们观察到,当工程师获得开箱即用的工具时,他们会编写更多测试,从而构建出稳定健康的代码库。

一个长期存在的难题是如何高效编写 React 测试。市面上已有诸多工具,例如 ReactTestUtilsenzyme。这些工具都很优秀且被广泛使用。然而工程师们常反馈,编写测试花费的时间甚至超过了开发组件本身。结果导致许多人完全放弃了测试,最终引发代码稳定性问题。工程师们告诉我们,他们真正需要的只是确保组件不会发生意外变更。

我们与 React 团队合作开发了全新的 React 测试渲染器,并将快照测试功能引入 Jest。请参考这个针对简单 Link 组件测试示例

import renderer from 'react-test-renderer';
test('Link renders correctly', () => {
const tree = renderer
.create(<Link page="http://www.facebook.com">Facebook</Link>)
.toJSON();
expect(tree).toMatchSnapshot();
});

首次运行此测试时,Jest 会创建如下所示的快照文件

exports[`Link renders correctly 1`] = `
<a
className="normal"
href="http://www.facebook.com"
onMouseEnter={[Function bound _onMouseEnter]}
onMouseLeave={[Function bound _onMouseLeave]}>
Facebook
</a>
`;

快照产物应与代码变更一同提交。我们使用 pretty-format 让快照在代码审查时具备可读性。后续测试运行时,Jest 会将渲染输出与之前的快照直接比对。若匹配则测试通过;若不匹配,可能是实现逻辑变更(需用 jest -u 更新快照),或是测试运行器发现了需要修复的代码缺陷。

如果修改示例中 Link 组件指向的地址,Jest 将输出以下结果:

快照测试

现在您知道:可通过 jest -u 接受变更,或在变更非预期时修复组件。要体验此功能,请克隆快照示例,修改 Link 组件后运行 Jest。我们已在 React 教程中新增快照测试指南。

此功能由 Ben AlpertCristian Carlesso 开发。

实验性 React Native 支持

通过构建不针对特定平台的测试渲染器,我们终于能完整支持未经模拟的 React Native。我们很高兴通过 jest-react-native 包为 Jest 提供实验性 React Native 支持。

可通过以下命令开始使用:yarn add --dev jest-react-native,并将预设添加到 Jest 配置中:

"jest": {
"preset": "jest-react-native"
}
信息

当前预设仅包含开始 React Native 测试所需的最简配置。我们期待社区贡献来完善此项目。请尝试使用并提交问题反馈或发送 PR!

为何采用快照测试?

在 Facebook 的移动应用中,我们使用名为"快照测试"的系统:渲染 UI 组件后截取屏幕快照,随后将记录的截图与工程师的变更进行比对。若截图不匹配,有两种可能:变更属于非预期行为,或可将截图更新至组件新版本。

虽然这是我们为 Web 端寻求的解决方案,但我们发现这类端到端测试存在许多问题,而快照集成测试能够解决:

  • 无脆弱性: 由于测试在命令行运行器中执行而非真实浏览器或手机,测试运行器无需等待构建、启动浏览器、加载页面或驱动 UI 来使组件进入预期状态(这些操作往往具有脆弱性,会导致测试结果不稳定)

  • 快速迭代速度: 工程师希望在一秒内获得结果,而非等待数分钟甚至数小时。如果测试不能像大多数端到端框架那样快速运行,工程师根本不会运行它们,甚至不愿编写测试

  • 调试便捷: 可以轻松进入集成测试的 JS 代码进行调试,无需尝试重现截图测试场景并在视觉差异中排查问题

由于我们相信快照测试在 Jest 之外也很有用,因此将该功能拆分为 jest-snapshot 包。我们期待与社区合作使其更通用,以便能与其他测试运行器集成并共享概念与基础设施

最后,引用一位 Facebook 工程师描述快照测试如何改变其单元测试体验的原话:

“我项目中最具挑战性的方面是保持每个测试用例的输入输出文件同步。功能的微小变更就会导致所有输出文件变化。使用快照测试后,我不再需要输出文件 - Jest 免费生成快照!我只需检查 Jest 如何更新快照,无需手动修改。” – 从事 fjs 项目的 Kyle Davis

Jest 的下一步计划

近期 Aaron Abramov 已全职加入 Jest 团队,负责改进 Facebook 广告产品的单元与集成测试基础设施。未来几个月 Jest 团队计划在以下领域重点改进:

  • 替换 Jasmine: Jasmine 正拖慢我们的进度且缺乏积极维护。我们已开始替换所有 Jasmine 匹配器,期待通过添加新特性彻底移除该依赖

  • 代码覆盖率: Jest 初创时期 Babel 等工具尚未出现。现有代码覆盖率支持存在诸多边界情况且运行不稳定,我们正在重写以彻底解决相关问题

  • 开发者体验: 涵盖从改进设置流程、调试体验、CLI 优化到完善文档等全方位提升

  • 模拟功能: 当前模拟系统(尤其是手动模拟)运行不佳且令人困惑,我们将使其更严格易用

  • 性能优化: 正在针对超大型代码库实施深度性能优化

一如既往,如有任何疑问或愿意贡献力量,欢迎随时联系我们!