Nx 插件 E2E 测试工程生成指南:使用 @nx/plugin:e2e-project 生成器搭建插件端到端测试
2026/9/12 5:56:10 网站建设 项目流程

Nx 插件 E2E 测试工程生成指南:使用 @nx/plugin:e2e-project 生成器搭建插件端到端测试

【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx

@nx/plugin包提供的e2e-project生成器用于为已存在的 Nx 插件自动搭建端到端(E2E)测试工程,它默认生成基于 Jest 的测试项目,也支持切换到 Vitest。本文以仓库中的官方文档 e2e-project-examples.md 为主线,结合生成器的参数 Schema、核心实现与单元测试,完整讲解命令用法、全部参数、生成产物与底层工作原理,帮助你为插件写出真正可运行的端到端测试。

e2e-project 生成器能做什么

在 Nx 中,插件(Nx Plugin)的开发流程通常包括编写生成器(generator)与执行器(executor),而验证它们在真实工作区中是否按预期工作,需要一套 E2E 测试工程:它会在测试环境中临时创建一个全新的 Nx 工作区,把刚构建的插件发布到本地 npm registry,再在临时工作区中安装该插件并执行相关命令来验证行为。

e2e-project生成器(generators.json 中注册为e2e-project)正是为此服务的脚手架:给定一个已存在的插件项目,它会生成一个名为<pluginName>-e2e的测试工程,并配置好:

  • 基于 Jest 或 Vitest 的e2etarget;
  • 通过 Verdaccio 搭建本地 npm registry,将插件发布后供测试工作区安装;
  • 一个包含默认冒烟测试的*.spec.ts文件,验证插件可以被安装到新建的工作区;
  • 与插件项目之间的隐式依赖关系。

核心参数一览

生成器的全部参数定义在 schema.json 中,其中pluginNamenpmPackageName为必填项:

参数类型默认值必填说明
pluginNamestring-待测试插件的项目名(x-priority: important
npmPackageNamestring-插件发布到 npm 时的包名(x-priority: important
pluginOutputPathstring-重要插件构建后的输出路径(x-priority: important
testRunnerjest|vitestjestE2E 测试使用的测试运行器
projectDirectorystring项目名插件所在目录,决定 E2E 工程放置位置
linternone|eslint|oxlint工作区当前使用的 linter用于运行 lint 检查的工具
jestConfigstring-Jest 配置文件路径
minimalbooleanfalse生成最小化 E2E 工程(不生成默认 executor/generator 的测试)
useProjectJsonboolean-使用project.json承载 Nx 配置,而不是内联到package.json
skipFormatbooleanfalse跳过文件格式化(内部选项)

其中testRunner由枚举约束,只能取jestvitest,默认jest。如果省略testRunner,生成器内部会执行options.testRunner = options.testRunner ?? 'jest'(见 e2e.ts),因此默认即 Jest 方案。

使用 Jest 的 E2E 工程(默认方案)

官方文档给出的第一个示例是基于 Jest 的默认用法。假设插件项目名为my-plugin,构建输出到dist/my-plugin,npm 包名为my-plugin,执行:

nx g @nx/plugin:e2e-project --pluginName my-plugin --npmPackageName my-plugin --pluginOutputPath dist/my-plugin

该命令会在工作区生成my-plugin-e2e项目。从 e2e.spec.ts 的断言可以还原出生成的工程结构与关键配置:

  • my-plugin-e2e/tsconfig.json:继承根目录tsconfig.base.json(若不存在tsconfig.base.json则回退为继承根tsconfig.json,见 e2e.spec.ts);
  • my-plugin-e2e/src/my-plugin.spec.ts:默认冒烟测试文件;
  • my-plugin-e2e/jest.config.cts:Jest 配置,使用ts-jest做 TypeScript 转换,并配置globalSetup/globalTeardown指向本地 registry 脚本;
  • my-plugin-e2e/tsconfig.spec.json:测试专用的 TypeScript 配置;
  • 项目targets.e2e:executor 为@nx/jest:jestdependsOn: ["^build"]options.jestConfig指向my-plugin-e2e/jest.config.cts,并开启runInBand: true(见 e2e.spec.ts);
  • 项目与插件之间建立了隐式依赖:implicitDependencies: ['my-plugin'](见 e2e.spec.ts)。

Jest 配置的生成逻辑

Jest 方案的配置由addJest函数完成(e2e.ts),其核心步骤为:

  1. 注册my-plugin-e2e项目配置(projectType: 'application'sourceRoot: '<root>/src');
  2. 调用@nx/jestconfigurationGenerator,以targetName: 'e2e'生成 Jest 配置;
  3. 通过addLocalRegistryScripts生成tools/scripts/start-local-registry.tstools/scripts/stop-local-registry.ts,并写入 Jest 配置的globalSetup/globalTeardown
  4. e2etarget 补上dependsOn: ['^build']runInBand: true

生成的jest.config.cts大致如下(以非 TS solution 布局为例,见 e2e.spec.ts):

module.exports = { displayName: 'my-plugin-e2e', preset: '../jest.preset.js', transform: { '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }], }, moduleFileExtensions: ['ts', 'js', 'html'], coverageDirectory: '../coverage/my-plugin-e2e', globalSetup: '../tools/scripts/start-local-registry.ts', globalTeardown: '../tools/scripts/stop-local-registry.ts', };

注意runInBand: truedependsOn: ['^build']的组合:^build保证在测试启动前先构建插件并将产物发布到本地 registry,runInBand则确保测试串行执行,避免多个 E2E 套件并发抢占共享的临时目录。

使用 Vitest 的 E2E 工程

官方文档的第二个示例是切换到 Vitest 的用法,只需在命令中追加--testRunner vitest

nx g @nx/plugin:e2e-project --pluginName my-plugin --npmPackageName my-plugin --pluginOutputPath dist/my-plugin --testRunner vitest

Vitest 方案由addVitest函数实现(e2e.ts),与 Jest 方案有几处关键差异:

  • 调用@nx/vitestconfigurationGenerator,以testTarget: 'e2e'生成配置,并指定testEnvironment: 'node'coverageProvider: 'none'(见 e2e.ts);
  • e2etarget 的 executor 为@nx/vitest:test,同样配置dependsOn: ['^build'],并额外设置maxWorkers: 1isolate: false(见 e2e.spec.ts)——这是因为多个测试套件共享tmp/test-project目录,必须串行执行,且 Vitest 4 移除了poolOptions,嵌套选项也无法在 executor 的 argv 往返中存活,因此使用标量选项;
  • Vitest 没有globalTeardown选项,其globalSetup文件必须同时导出setupteardown。因此生成器会创建tools/scripts/vitest-global-setup.ts包装器(e2e.ts),内容为:
export { default as setup } from './start-local-registry'; export { default as teardown } from './stop-local-registry';

若缺少teardown,setup 阶段启动的 Verdaccio 进程会在测试结束后残留(见 e2e.spec.ts 的对应断言)。

  • 生成器会在vitest.config.tsvitest.config.mtstest配置块中注入globalSetup路径。

一个值得注意的细节:@nx/vitest只会推断testtarget,如果没有显式的e2etarget,nx e2e命令就不存在,^build也就不会在本地 registry 发布插件前运行(见 e2e.spec.ts 的测试说明)。因此 Vitest 方案的e2etarget 是显式注册的。

底层原理:临时工作区、本地 registry 与冒烟测试

E2E 测试之所以能验证插件的真实行为,靠的是 e2e.ts 中编排的完整流程:

  1. 校验插件存在validatePlugin会读取插件的项目配置,若项目不存在则抛出Project name "<pluginName>" doesn't not exist.(e2e.ts),并在 e2e.spec.ts 中通过正反两个用例验证;
  2. 生成工程文件:基于模板files/目录渲染my-plugin-e2e下的文件;
  3. 配置 Verdaccio 本地 registrysetupVerdaccioaddLocalRegistryScripts一起完成本地 npm registry 的搭建与启停脚本生成;
  4. testRunner分支接入 Jest 或 Vitest
  5. 解除插件的 private 标记updatePluginPackageJson会删除插件package.json中的private字段,因为发布到本地 registry 需要非私有包(e2e.ts);
  6. 按需配置 lint 与 TS solution 工程

默认冒烟测试模板

生成的测试文件来自模板simplePluginName.spec.ts__tmpl__,其测试策略是:

  • beforeAll中通过createTestProject()使用create-nx-workspace@latesttmp/test-project目录创建一个全新的临时工作区(--preset apps --nxCloud=skip --no-interactive),随后把构建好的插件以@e2e版本标签安装进去;
  • 安装预算为 300 秒(beforeAll(..., 300_000)),因为该 hook 会同步执行两次安装,必须覆盖冷包管理器缓存场景(见模板文件注释,以及 e2e.spec.ts 中预算不得低于 240_000 的回归测试);
  • it('should be installed')通过执行包管理器的 list 命令验证插件确实被安装(npm ls在未正确安装时会失败);
  • afterAll递归清理临时工作区。

运行 E2E 测试:

nx e2e my-plugin-e2e

高级选项与边界情况

控制项目放置位置:projectDirectory

当插件位于嵌套目录(如namespace/my-plugin)时,可通过projectDirectory指定,生成的 E2E 工程会落到<directory>-e2e下:

nx g @nx/plugin:e2e-project --pluginName my-plugin --npmPackageName my-plugin --pluginOutputPath dist/namespace/my-plugin --projectDirectory namespace/my-plugin

此时项目根目录为namespace/my-plugin-e2e(见 e2e.spec.ts)。

最小化工程:minimal

设置--minimal后,生成器不会生成针对默认 executor 和 generator 的测试,适合只想验证插件可安装、可加载的场景。

Lint 配置:linter

--linter支持eslintoxlintnone,默认继承工作区现有 lint 工具。指定--linter eslint时会生成my-plugin-e2e/eslint.config.mjs,内容为导入根配置并展开:

import baseConfig from '../eslint.config.mjs'; export default [...baseConfig];

(见 e2e.spec.ts 的快照断言。)

TypeScript solution 布局

当工作区采用 TS solution 布局(package.json中配置workspaces、根tsconfig.json使用references)时,生成器会走isTsSolutionSetup分支:为 E2E 工程生成独立的package.json,把新的 tsconfig 引用追加到根tsconfig.json,并更新工作区文件;Jest 转换器也随之切换为@swc/jest并生成.spec.swcrc(见 e2e.spec.ts)。

总结

@nx/plugin:e2e-project生成器把「为插件搭建端到端测试工程」这一重复性工作封装为一条命令:

  • 默认 Jest 方案nx g @nx/plugin:e2e-project --pluginName my-plugin --npmPackageName my-plugin --pluginOutputPath dist/my-plugin
  • Vitest 方案:追加--testRunner vitest
  • 核心机制:构建插件 → 发布到 Verdaccio 本地 registry → 在create-nx-workspace创建的临时工作区中安装@e2e版本插件 → 冒烟测试验证安装成功。

其参数定义、生成逻辑与全部行为均可在仓库中直接追溯:schema.json、e2e.ts 与 e2e.spec.ts,模板文件位于 files 目录。阅读这些文件可以进一步了解每个选项对生成产物的具体影响,并按需裁剪你的插件测试策略。

【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询