2023 年 Angular 测试——过去、现在和未来
Angular 16弃用了 Karma,并引入了实验模式的 Jest。这是否意味着我们目前没有稳定的测试框架?我们应该切换到 Jest 吗?Karma 到底有什么问题?
如果您更喜欢观看视频而不是阅读,那么这适合您:
在本文中,我想回答这些问题以及更多问题。
首先,让我们回顾一下 Angular 16 之前的情况。我将介绍 Jest 和 Jasmine 之间的区别,并解释 Karma 的作用。然后,我们将深入探讨 Jest,并讨论为什么当前基于社区的解决方案可能更为理想。最后,我们将展望未来,看看 Angular 会带来什么。
Angular 测试全景
粗略地说,我们使用两种不同类型的框架来测试我们的 Angular 应用程序:一种用于单元/组件测试,另一种用于端到端测试。对于端到端测试,我们使用 Cypress、Playwright 等框架,或者一些 Webdriver 的衍生产品,例如 Selenium 或 WebDriverIO。
当谈到组件测试时,存在一些重叠,因为 Cypress 也支持它。
对于单元/组件测试,我们使用 Jasmine 或 Jest。Angular CLI 的官方支持一直是 Jasmine。如果我们想切换到 Jest,通常会选择 Nx 或使用 just-jeb/angular-builders 中的构建器。
玩笑还是茉莉?
在 Angular 中,Jasmine 始终与 Karma 配套使用。Karma 充当 Jasmine 的载体,将测试嵌入到浏览器中。浏览器上下文的优势在于,测试可以访问 Web API 以及浏览器提供的所有其他功能。另一方面,浏览器会增加一些开销。
Jest 提供了一种替代方案。我们可以在 Facebook 找到 Jest 的起源。他们 fork 了 Jasmine,并在性能方面进行了改进。
Jest 不使用浏览器,而是使用 jsdom。jsdom 是一个模拟器,它提供了一个 DOM,其中包含部分 Web API,允许我们选择 DOM 本身并与之交互。由于使用了模拟器,其开销比使用真实浏览器要小得多。另一方面,我们可用的功能有限。例如,我们无法通过 audio 标签播放音乐,也无法将内容存储在本地存储中。不过,在大多数情况下,这与我们在测试中想要实现的功能不同。
其他“强大功能”包括内置并行化和出色的监视模式。监视模式仅执行受当前更改影响的测试。如果我们有 10,000 个测试,但最近的更改仅影响其中 10 个,则 Jest 只会运行这些测试。
这些特性使得 Jest 成为主导的测试框架,不仅在 Angular 中,而且在整个 JavaScript 领域中。
Jest 的弱点:ES 模块
不幸的是,在过去的几年里,我们看到了一些奇怪的错误消息,例如“导入未定义”,并且性能大幅下降。
事实证明,Jest 与 Angular 的集成程度与 Jasmine 并不在一个水平上。Jest 需要自行完成编译。因此,对于 Angular,它会获取我们测试的源代码,并将其编译为 JavaScript。
Angular 编译器负责这项工作,它运行在 TypeScript 编译器之上。它了解所有元数据,以及这些元数据对最终代码的意义。
它在 Jest 中是如何运作的?秘诀在于jest-angular-preset项目。它包含了所有的逻辑,并且Nx和just-jeb/angular-builders都依赖于它。
不幸的是,jest-angular-preset 并不能解决 Jest 构建过程中的所有问题。
ECMAScript 模块(ESM)即将问世。它是 JavaScript 文件的官方加载标准,某种程度上可以说是 CommonJS(CJS)的继承者。许多第三方库纷纷加入 ESM 的行列,并专门以该格式发布。Angular 尤其强调其库只支持 ESM 格式。
Jest 措手不及。它只支持旧版 CJS。将我们的测试和应用程序代码编译成 CJS 对 Jest 来说不是什么大问题。问题出在 node_modules 目录中,尤其是 Angular 及其库,它们现在已不再支持 CJS。
Jest 必须将如此大量的代码从 ESM 转译为 CJS。这显著降低了 Jest 的速度。因此,Jasmine(由 Angular 负责构建)突然超越 Jest 也就不足为奇了。
此外,事实证明,Jest 的开发只有一个人负责。Facebook/Meta 上次贡献代码是在几年前。因此,Simen Bekkhen 不得不独自一人维护 Jest。更糟糕的是,他对 ESM 的标准化流程感到失望,并休假了一段时间。
让我们回到今天。Jest 现在是开源基金会的一部分,拥有众多贡献者。Simen 正在开发Jest 的 ESM 支持。它仍处于实验阶段,但 Angular 社区插件已经默认使用它了。
情况已经好多了。然而,仍然有可能陷入性能陷阱。Tomas Trajan 专门写了一篇文章来探讨这个问题。
Angular CLI 中的实验性 Jest 模式
回到现在。我们看到 Jest 正在复苏,正在追赶它以前的状态……突然,Angular 团队介入了。
Angular 开发者调查显示,测试方面仍有改进空间。因此,纵观测试现状,Angular 团队决定正式支持 Jest。
目前,它处于实验模式。我们可以尝试一下,但不要期待太多。实验模式与我们在 Angular 14 中看到的独立组件开发者预览版不同。我们更应该将其视为概念验证。
官方的 Jest 集成不会走 Nx & Co 的路。Jest 将不再负责构建。Angular 将接管。
这意味着 Jest 会获取一堆 *.mjs 文件。无需遍历 node_modules、进行转译等操作。相反,Jest 可以立即开始执行。
但这还不是全部。例如,Angular 使用全新的 esbuild 而不是 webpack。据说在某些情况下,esbuild 的性能比 Webpack 高出50 到 100 倍。它也已多次证明了自己的优势。例如,Vitest 和 Vite 都在内部使用它。它们都以其性能而闻名,而这得益于 esbuild。
因此我们可以说 Angular 中的测试当前状态如下:
切换到 Jest
您可以按照以下方法尝试一下。
- 打开您的
angular.json
并替换中的构建器test
,其值应@angular-devkit/build-angular:karma
为@angular-devkit/build-angular:jest
。 - 通过安装必要的依赖项
npm install -D jest @types/jest jest-environment-jsdom
。 - 找到并将属性中的
tsconfig.spec.json
值替换为。jasmine
types
jest
现在只需执行npx ng test
。你应该会看到 Angular 构建器在 dist 中创建了一个 test-out 文件夹,其中包含以 mjs 为文件扩展名的测试文件。这就是 Jest 的运行位置。
您还不想在生产环境中使用它。Jest 的监视模式不可用,您的 IDE 不会运行测试,并且您无法通过 jest.config.ts 自定义 Jest。
Jasmine 和 ModernWeb
那么 Karma 的弃用又如何呢?Karma 的任务是启动浏览器并嵌入 Jasmine 测试。因此,Karma 的弃用并不意味着 Jasmine 也被弃用了。
此外,在 Angular 16 中,Karma 仍然功能齐全。因此,您现有的测试仍将像以前一样有效。
在未来的版本中,Angular 将会用ModernWeb的 web-test-runner 取代 Karma 。那个未来版本可能已经是 Angular 17 了。ModernWeb 是一个将测试嵌入到浏览器中的现代社区项目。
从 Karma 到 ModernWeb 的转变甚至可能不被察觉。我们应该没什么可做的了。不过,我们拭目以待吧 ;)
更有趣的问题是为什么?
Karma 从 Angular 1(AngularJs)开始就一直存在。被称为“Angular 之父”的 Misko Hevery 是其合著者,而 Karma 几乎是 Angular 的专属。
AngularJs 及其生态系统发展至今已过去了相当长一段时间。随着像 web-test-runner 这样的社区项目的出现,Angular 团队已经没有必要再固守 Karma 了。
因此,可以预见,Angular 测试的未来将提供 Jasmine/WebTestRunner(ModernWeb)和 Jest 的组合。
概括
2023 年,Angular 凭借 Signals 和 Hydration 取得了长足进步。在测试方面,Angular 也在加速发展。它将集成 Jest,这样 Angular 就可以提供完整的构建功能,而 Jest 只需执行那些测试即可。在目前的社区解决方案中,Jest 也必须自行构建,这在过去曾造成过一些问题。
Jasmine 仍将是一个支持测试框架。然而,它将进行现代化升级,由 web-test-runner 而非 Karma 提供浏览器上下文。
无论我们看向何处,Angular 中都在发生着好事!
您可以找到一个 Github 存储库,其中包含 Angular 16 中所有可能的变体。
rainerhahnekamp /角度测试状态
Monorepo 展示 Angular 中的当前测试状态 (16)
如果您对有关测试的更多内容感兴趣,您可能想加入我们即将举行的测试研讨会之一:
🇩🇪 德语工作坊:
🇺🇸英语工作坊:
鏂囩珷鏉ユ簮锛�https://dev.to/this-is-angular/angular-testing-in-2023-past-present-and-future-j5m