首页
/ Cypress CLI 深度解析:命令体系、构建与测试流程、子包 API 与 Module API

Cypress CLI 深度解析:命令体系、构建与测试流程、子包 API 与 Module API

2026-09-05 18:00:46作者:范垣楠Rhoda

本文以 Cypress 仓库 cli/ 目录的官方文档为核心,完整讲解 Cypress CLI 的职责边界、npm 包的构建与测试流程、子包(sub-package)机制与 Module API 用法,并结合 cli/libcli/scripts 等源码给出可对照的实现证据。读完后你将掌握:如何从仓库构建并打包 Cypress npm 包、如何跑 CLI 单元测试与快照更新、如何新增一个 cypress/* 子包,以及如何用 cypress.run() 模块接口在本地驱动测试。

CLI 是什么:职责与命令体系

Cypress 仓库中的 CLI 模块(位于 cli/)用于构建在终端中运行的 cypress npm 包。据 cli/README.md,CLI 承担以下职责:

  • 打印 CLI 命令(help)
  • 安装 Cypress 可执行文件(install)
  • 打印当前 Cypress 版本(version)
  • 从终端运行 Cypress 测试(run)
  • 打开交互式 Test Runner(open)
  • 验证 Cypress 已正确安装且可执行(verify)
  • 管理 Cypress 二进制缓存(cache)
  • 传入改变测试运行/录制方式的选项(浏览器、spec 文件、分组、并行等)

这些职责在源码中一一对应到具体模块。cli/lib/cli.ts 基于 commander 注册了完整的命令集,其中 knownCommands 白名单(cli/lib/cli.ts#L157-L171)为:cachehelp-h--helpinstallopenruntapverify-v--versionversioninfo。值得注意的是,run 命令额外注册了一个面向开发者的 cypress tap 子命令,用于从命令行发现、控制并查询一个 open 模式下的 Cypress 会话(见 cli/lib/cli.ts#L595-L613)。

cypress run 常用选项

run 命令的全部选项定义在 cli/lib/cli.ts#L258-L290addCypressRunCommand 中,各选项的官方描述集中在同文件的 descriptions 对象里。摘录最常用的部分:

选项 说明(源自源码描述)
-b, --browser <name-or-path> 指定浏览器名称运行;若提供文件系统路径,则尝试使用该路径的浏览器
-c, --config <config> 设置配置值,逗号分隔,覆盖 cypress.config.{js,ts,mjs,cjs} 中的同名值
-C, --config-file <file> 配置文件路径,默认为 cypress.config.{js,ts,mjs,cjs}
-e, --env <env> 设置环境变量,逗号分隔,覆盖配置文件或 cypress.env.json
--component / --e2e 运行组件测试 / 端到端测试
--headed / --headless 显示浏览器(headed)/ 无头运行(cypress run 的默认行为)
--record [bool] / -k, --key <key> 录制运行结果并发送到 Cypress Cloud;Record Key 也可由 CYPRESS_RECORD_KEY 环境变量提供
--parallel / --group <name> / -t, --tag <tag> 启用跨机器/进程并发与负载平衡;为云端录制运行指定命名分组 / 命名标签
-r, --reporter / -o, --reporter-options 指定 mocha reporter(默认为 spec),并传入 reporter 选项
-s, --spec <spec> 只运行指定 spec 文件,默认为全部
-p, --port <port> / -P, --project <path> 覆盖配置中的端口;指定项目路径

此外,--dev--inspect--inspect-brk 是为开发 Cypress 自身预留的内部标志,源码中通过 maybeAddDevFlag / maybeAddInspectFlagscli/lib/cli.ts#L315-L331)只在实际传了 --dev 时才注册,从而避免公开发布的 --help 输出宣传这些会报错的标志。另一个细节是 parseVariableOptscli/lib/cli.ts#L75-L110):它容忍 --spec spec1 spec2 这种空格分隔写法但会打印警告,建议改用逗号分隔;最常见的触发原因是未加引号的 glob 模式,应写成 cypress run --spec "**/*.spec.js"

构建 npm 包

文档指出构建流程见 scripts/build.js,并特别强调:构建产物(npm 包)会以 cli/NPM_README.md 作为其公开发布的 README 文件

结合 cli/package.json 可以看到实际由 npm script 驱动的构建链:

"prebuild":  "yarn clean-cli-build && yarn postinstall && tsx ./scripts/prep-build-dir.ts",
"build":     "rollup -c",
"postbuild": "yarn make-bin-executable && yarn sync-build-dist && yarn prepare-package-json && yarn bundle-ct-frameworks"
  • prebuild 先清理旧的 builddist 产物,再执行 postinstall(打补丁 patch-package 并运行 tsx ./scripts/sync-typedefs.ts 同步类型定义)与构建目录准备脚本;
  • build 用 Rollup 打包(配置见 cli/rollup.config.mjs),输出 dist/index.js / dist/index.mjs
  • postbuild 依次使 bin/cypress 可执行、同步构建产物、准备 package.json,最后执行 bundle-ct-frameworks(见下文子包一节)。

package.jsonfiles 字段声明了发布进 npm 包的内容:bindisttypes/**/*.d.ts,以及 mount-utilsvuereactangularsvelte 五个子包目录。engines 字段要求 Node ^22.0.0 || ^24.0.0 || >=26.0.0bin 字段将 cypress 命令映射到 bin/cypress

测试

自动化测试

从仓库根目录运行 CLI 包的单元测试(--scope cypress 将测试范围限定在 cli/ 包):

yarn test-unit --scope cypress
yarn test-watch --scope cypress
yarn test-debug --scope cypress

对应的实际实现是 cli/package.json 中的 test-unit: vitest runtest-debug: npx vitest --inspect-brk --no-file-parallelism --test-timeout=0(CLI 已迁移到 Vitest,测试位于 cli/test/lib/,含 cli.spec.tscypress.spec.tsutil.spec.tsexec/tasks/tap/ 等子目录)。

更新快照

在任意测试命令前加上 SNAPSHOT_UPDATE=1 前缀即可更新快照(基于 snap-shot-it 的快照机制):

SNAPSHOT_UPDATE=1 yarn test-unit --scope cypress

类型检查(dtslint)

使用 dtslint 做类型检查时(yarn types,即 dtslint types,作用对象为 cli/types/),可能需要先删除已有的 TypeScript 安装以复现新版 TypeScript(如 @next)下的问题,例如在 macOS 上执行 rm -rf ~/.dts/typescript-installs

手动构建并测试 npm 包

按文档给出的完整流程,在仓库根目录执行:

yarn
yarn build

这会生成 cli/build 文件夹。接着:

cd cli/build
yarn pack

会生成一个归档文件,通常命名为 cypress-v<version>.tgz。该归档可以在其他项目中安装;但由于此时通常还没有对应的二进制文件,需要跳过二进制下载(--ignore-scripts)。例如在 cypress-example-kitchensink 之类的示例项目里:

yarn add ~/{your-dirs}/cypress/cli/build/cypress-v13.13.2.tgz --ignore-scripts

子包 API(Sub-package API):cypress/vue 这类深层导入如何解析

文档提出的核心问题:How do deep imports from cypress/* get resolved?

cypress npm 包出厂时已内置了主流前端框架的挂载(mounting)库——这是 Cypress 提供“再导出子包(re-exported sub-packages)”的第一批示例。这些子包沿用它们在 npm 上发布时的命名规则,只是去掉开头的 @。以 Vue 挂载库为例,如果单独安装了 @cypress/vue,你会这样写:

import { mount } from '@cypress/vue'

而借助子包 API,可以直接从 Cypress 本体导入,无需额外安装依赖:

import { mount } from 'cypress/vue'

两者唯一差别就是导入名;如果你需要锁定某个外部子包的特定版本,仍然可以单独安装并直接导入它。这个能力在 cli/package.jsonexports 映射中有明确定义(cli/package.json#L128-L169):./vue./react./angular./svelte./mount-utils 分别指向各自子包的 dist 入口与类型声明,./package.json 也被显式导出以便工具链读取。

从构建脚本看,子包目录是在 postbuild 阶段由 cli/scripts/bundle-ct-frameworks.ts 复制进构建产物的:该脚本维护 npmModulesToCopy = ['mount-utils', 'react', 'vue', 'angular', 'svelte'],并把每个 cli/<子包目录> 拷贝到 cli/build/<子包目录>,最终随 files 字段一起发布。

新增一个子包的步骤

文档给出了新增子包的完整流程(原文示例以 npm/vue 为例):

  1. 确保该子包的 rollup 构建是自包含的,或其所有依赖也在 CLI 的 package.json 中声明;
  2. 在要嵌入的子包的 postbuild 脚本中调用 node ./scripts/sync-exported-npm-with-cli.js(相对子包目录;仓库根目录下的 scripts/sync-exported-npm-with-cli.js 即该同步脚本);
  3. 把子包名字加入以下位置:
    • cli/.gitignore
    • cli/scripts/post-build.js
    • .eslintignore(cli/sub-package 项下)
  4. 不要手动更新 package.json——运行 yarn build 会自动完成这一过程;
  5. 提交变更文件。

说明:当前仓库中该流程对应的构建入口体现在 cli/package.jsonpostbuild 脚本链(make-bin-executable → sync-build-dist → prepare-package-json → bundle-ct-frameworks),新增子包时同步维护 bundle-ct-frameworks.tsnpmModulesToCopy 列表与 package.jsonexports/files 声明即可。

Module API:以编程方式驱动 Cypress

除了命令行,CLI 也导出了一组模块接口,用于在 Node 脚本中直接调用。cli/lib/index.ts 在末尾以具名导出的方式暴露 openrunclidefineConfigdefineComponentFrameworkcli/lib/index.ts#L43-L56)——注释特意说明必须采用这种导出形式,因为在 CJS 语境下 require('cypress') 时 default export 会导致破坏性变更。实际实现在 cli/lib/cypress.ts

  • run(options):先校验 options.project,再通过 util.normalizeModuleOptions 归一化选项,用 tmp 生成临时结果文件作为 outputPath,执行 runModule.start 后读回 JSON 结果返回;找不到结果时返回 {status: 'failed', failures, message} 结构;
  • open(options):打开交互式 GUI;
  • cli.parseRunArguments(args):把 ['cypress', 'run', '--browser', 'firefox'] 这样的参数数组解析成可直接喂给 cypress.run() 的选项对象(底层即前述 cliImport.parseRunCommand);
  • defineConfig / defineComponentFramework:透传配置对象,仅为编辑器提供自动补全。

文档给出的本地测试 Module API 的示例(要求 dev 标志,否则会在二进制检查处失败):

/* @ts-ignore */
import cypress from '../../cli/lib/cypress'

const run = cypress.run as (options?: Partial<CypressCommandLine.CypressRunOptions>) => Promise<CypressCommandLine.CypressRunResult | CypressCommandLine.CypressFailedRunResult>

run({
  spec: './cypress/component/advanced/framer-motion/Motion.spec.tsx',
  testingType: 'component',
  /* @ts-ignore */
  dev: true,
}).then(results => {
  console.log(results)
})

其中 dev: true 是本地测试的必需项:发布版 CLI 会先校验二进制缓存,未打包的开发版会在此处报二进制错误。

关键命令的源码级行为

最后补充几个与 README 职责清单直接对应、且值得了解的底层行为(均可在源码中验证):

  • installcli/lib/tasks/install.ts 中的 start 处理了 CYPRESS_INSTALL_BINARY(设为 0 可跳过安装;设为版本、本地 zip 路径或 URL 可覆盖默认版本)与 CYPRESS_CACHE_FOLDER(覆盖缓存目录并提示旧安装可能找不到);对 pre-release 构建会打印包含 commit SHA/分支/时间的警告,并改用预发布二进制的下载地址。下载与解包以 listr2 任务序列执行(Downloading → Unzipping → Finishing Installation),CI 环境自动切换为带时间戳的逐行输出。
  • cachecli/lib/tasks/cache.ts 提供 list(用 cli-table3 渲染 version / last used / size 表格,--size 开启大小统计)、pathclear(直接删除缓存根目录)、prune(删除除当前版本外的所有二进制缓存,且显式跳过 bundles 与 sessions 目录,见 EXTERNAL_CACHE_ENTRIES,避免误删会话记录)。
  • versioncli/lib/exec/versions.ts 汇总 package / binary / Electron / 内置 Node 四个版本;若设置了 CYPRESS_RUN_BINARY 环境变量则以其指向的二进制目录为准,并给出合法性校验。cypress version --component <package|binary|electron|node> 可只打印单个组件版本。
  • infocli/lib/exec/info.ts--mode=info 启动二进制,并打印 Application Data、Browser Profiles、Binary Caches 路径,以及 Cypress 版本、系统平台与内存信息;pre-release 构建还会输出 commit SHA、分支与时间。

小结

cli/README.md 虽然篇幅不长,但完整定义了 CLI 模块的“职责清单 + 构建 + 测试 + 子包 + Module API”五条主线。对照 cli/lib/cli.ts 的命令注册、cli/package.json 的脚本与 exports 映射、cli/scripts/bundle-ct-frameworks.ts 的子包拷贝逻辑,可以确认文档中的每一步流程都落在真实实现上:yarn build 产出 cli/buildyarn pack 产出 cypress-v<version>.tgz 并以 --ignore-scripts 安装跳过二进制下载、cypress/vue 这类深层导入由 npm exports 字段解析、cypress.run() 模块接口则以 dev: true 作为本地开发前提。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.79 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
988
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384