12k
All articles

Cypress 16 新特性一览

了解 Cypress 16 的变化:原生 HTTP/2、更快的测试、已移除的 API 和迁移修复,并了解升级到 Cypress 16.1.0 或更高版本的原因。

OpenReplay Team
OpenReplay Team
Cypress 16 新特性一览

Cypress 16 在 Chrome、Chromium 和 Edge 中改用浏览器原生网络栈运行,并支持 HTTP/2。默认的输入速度和可见性检查也更快了。此外,它移除了 Cypress.env() 和 cy.exec()。请升级到 16.1.0 或更高版本,不要使用 16.0.0。

大版本升级出问题,往往不在本地,而在 CI。可能是 support 文件中调用了已移除的 API 而抛出异常,也可能是某次运行中途停止输出,直到任务超时。

本文涵盖 Cypress 16.0.0(2026 年 9 月 1 日)和 16.1.0(2026 年 9 月 15 日),内容包括:哪些方面变快了,测试写法有哪些变化,哪些地方会出问题以及如何修复,以及应该锁定哪个版本。基础知识请参阅 使用 Cypress 进行端到端测试。

核心要点

  • 在 Cypress 16 中,只要服务器支持,Chrome、Chromium 和 Edge 就会使用 HTTP/2 或 HTTP/3。Firefox、WebKit 和 Electron 仍使用 HTTP/1.1。
  • Cypress.env() 已被移除。敏感信息请使用 cy.env(),这些值会保留在 Node 进程中,直到测试主动请求。可以在浏览器中暴露的值则使用 Cypress.expose()。
  • cy.intercept() 的 API 保持不变,但在原生网络路径下,req.httpVersion 不再提供,压缩相关的响应头会缺失,重新验证的响应返回 200 而不是 304。
  • Cypress 16 要求 Node.js 22.x、24.x 或 >=26.x,不再支持 Node 20 和 25。
  • 请使用 16.1.0 或更高版本。16.1.0 修复了 16.0.0 的两个回归问题:一是 Chrome 系浏览器的运行可能卡住且没有任何输出,二是 blockHosts 未生效。

Chrome、Chromium 和 Edge 默认启用 HTTP/2

在 Cypress 16 中,Chrome、Chromium 和 Edge 直接在浏览器自身的网络栈上拦截测试流量,不再经过 Cypress 代理。被测应用直接连接到你的服务器,并使用双方都支持的最佳协议,包括 HTTP/2 和 HTTP/3。Firefox、WebKit 和 Electron 仍沿用传统的 HTTP/1.1 路径。

切换到原生 HTTP/2 意义重大。HTTP/1.1 对每个源只允许少量并行连接,包含数百个资源的页面只能排队加载。HTTP/2 则把所有请求作为流(stream),在单个连接上多路复用。Cypress 官方基准测试显示,加载 1,000 张图片的页面,耗时从 HTTP/1.1 下的 3,896ms 降到了 HTTP/2 下的 1,362ms。由于官方公告没有说明测试环境,这个数字只能说明改进方向,不能用来预测你的测试套件会快多少。

原生 HTTP/2 还让流式 UI 可以在 Cypress 16 中进行测试。在 HTTP/1.1 下,浏览器对每个域名最多只允许 6 个 Server-Sent Events 连接,因此实时通知之类的功能以往很难测试。在 HTTP/2 下,并发流的数量由服务器和浏览器协商,Cypress 给出的常见默认值是 100。

Cypress 16 也不再为被测应用终止 TLS,因此浏览器会校验源站的真实证书。如果你使用自签名开发证书或内部 CA,16.1.0 新增了 trustedCertificates 配置项。

Cypress 16 中的测试速度变化

Cypress 16 调整了三项影响速度的默认设置,每一项都可以改回原来的行为。

  • 按键延迟变为 0ms,此前为 10ms。如果某些输入框依赖输入节奏(例如带防抖的搜索框),可以恢复原来的延迟:
Cypress.Keyboard.defaults({ keystrokeDelay: 10 })
cy.get('[data-cy=search]').type('laptop', { delay: 10 })

在 16.0.0 中,把 keystrokeDelay 写进 TypeScript 配置文件会导致编译失败,16.1.0 已修复这个问题。

  • 可见性检查改用新版算法。 新算法基于浏览器原生的 Element.checkVisibility(),visibilityStrategy 默认值为 'modern'。
  • manageBrowserMemory 默认开启。 测试运行期间,Cypress 会定期检查内存占用。一旦超过设定阈值,就会在下一个测试开始前执行垃圾回收。这一清理过程本身会耗时,所以对于较轻量的测试套件,关闭该选项可能反而更快。关闭之前,请先分别在开启和关闭两种情况下给测试套件计时。

Cypress 16 的测试写法有哪些变化?

在 Cypress 16 中,Cookie 和存储的读取命令会像其他查询一样自动重试,环境变量的访问也拆分成了两个独立的 API。

cy.getCookie()、cy.getCookies()、cy.getAllCookies()、cy.getAllLocalStorage() 和 cy.getAllSessionStorage() 现在都是可重试的查询命令,超时由 defaultCommandTimeout 控制。它们不再使用 responseTimeout,不过 cy.setCookie() 仍然使用。链式调用 .should() 时,命令会一直重试直到断言通过;如果把检查写在 .then() 中,则只执行一次,不会重试。

cy.getCookie('auth_token').should('have.property', 'value')

如果你的测试套件覆盖了上述任一命令,请改用 Cypress.Commands.overwriteQuery()。Cypress.Commands.overwrite() 对这些命令已不再生效。

Cypress.env() 在 15.10.0 中已被弃用,现在已正式移除。cy.env() 是异步的:它从 Node 进程中读取敏感值,并且只把你指定的键交给测试。Cypress.expose() 是同步的,适用于可以在浏览器中公开的值。

// Before (Cypress 15)
const token = Cypress.env('STRIPE_KEY')

// After (Cypress 16)
cy.env(['STRIPE_KEY']).then(({ STRIPE_KEY }) => {
  cy.request({ url: '/api/charge', headers: { Authorization: STRIPE_KEY } })
})
const apiBase = Cypress.expose('PUBLIC_API_URL')

cy.env() 会在 Command Log 中记录键名,但不会记录值。不过,这层保护只到它把对象交给你为止:.its()、.invoke()、断言或失败的命令都可能把值打印出来,所以请把敏感信息限制在 .then() 内部使用。单个测试和测试套件级别的覆盖配置现在使用 expose: {...},不再使用 env: {...}。allowCypressEnv 也已移除。

Cypress 16 的破坏性变更及修复方法

Cypress 16 的大多数破坏性变更都是直接移除,迁移指南为每一项都提供了对应的替代方案。真正需要花心思处理的是 cy.intercept()。

cy.intercept() 的 API 本身没有变化,但在原生网络路径下有几处不同:req.httpVersion 不再提供;响应体到达时已经解码,所以 content-encoding 等压缩相关的响应头会缺失;重新验证的响应返回 200 而不是 304;在 HTTP/2 和 HTTP/3 下,res.statusMessage 为空。此外,responseTimeout 也不再限制响应处理函数。如果迟迟没有收到响应,Cypress 会在固定的 30 秒后放弃;如需其他时限,请在 cy.wait() 上设置。断言应针对应用行为,而不是传输层细节。Cypress 中的 Mock 与 Stub 一文中介绍的模式依然适用。

// Before: expect(req.httpVersion).to.eq('1.1')
cy.intercept('GET', '/api/cart').as('cart')
cy.visit('/checkout')
cy.wait('@cart', { timeout: 15000 }).its('response.statusCode').should('eq', 200)

以下是 16.0.0 破坏性变更的完整列表,以及不处理时会发生什么:

变更不处理的后果修复方法
移除 cy.exec() / execTimeoutcy.exec() 抛出异常;execTimeout 输出警告并被忽略将逻辑迁移到 cy.task() 中,并使用 taskTimeout
移除 cy.end()命令报错删除相关调用
通过 Cypress.config() 设置 viewportWidth/viewportHeight/blockHosts不再允许在运行时设置(此前会作用于下一个测试)在 describe/it 配置中设置,或调用 cy.viewport()
experimentalMemoryManagement输出警告并被忽略删除该配置;如需关闭,使用 manageBrowserMemory: false
experimentalFastVisibility已被替代删除该配置;现在由 visibilityStrategy 控制
移除 experimentalSourceRewriting该选项失效删除该配置;遇到 SRI 错误时使用 removeSRIAttributes
CoffeeScript.coffee 文件无法再被解析改用 JS/TS,或使用 @cypress/webpack-preprocessor
Node.js不再支持 Node 20 和 25使用 Node 22.x、24.x 或 >=26.x
组件测试不再支持较旧的工具链Angular 21.0.0+、Vite 8.0.0+、Next.js 15.0.4+ 或 16+
Electron已弃用,但仍可运行将 CI 切换到 Chrome 或其他已安装的浏览器

对于视口设置,请将其移到代码块配置中:

describe('mobile nav', { viewportWidth: 375, viewportHeight: 667 }, () => {
  it('opens the menu', () => { /* ... */ })
})

Cypress 16 的回退选项只是临时方案

Cypress 16 提供了两个回退选项,changelog 已将两者都标记为弃用。forceHttp1: true 会让所有浏览器重新走传统代理路径。这个选项在引入它的同一个版本中就被标记为弃用,Cypress 计划在 Chrome 和 Firefox 都对原生路径提供长期支持后将其移除。visibilityStrategy: 'legacy' 会恢复旧的可见性算法。该选项同样已被弃用,changelog 建议只把 legacy 值当作迁移期间的过渡手段。

forceHttp1 和 visibilityStrategy: 'legacy' 应该用来排查失败原因,而不是作为永久配置。如果开启某个选项后失败消失了,就对照官方文档中列出的原生网络差异找出原因,改写断言,然后移除该选项。

结论:升级到 Cypress 16.1.0 或更高版本,不要用 16.0.0

建议升级,并锁定 16.1.0 或更新的 16.x 版本,不要使用 16.0.0。16.1.0 修复了 16.0.0 的一个回归问题:在 Chrome、Chromium 和 Edge 中,运行可能中途停止输出且永远无法结束。它还修复了 blockHosts 在这些浏览器中不生效的问题:发往被屏蔽主机的请求本应以 503 失败,实际却发到了网络上。这意味着依赖屏蔽主机的测试套件在 16.0.0 上可能会通过,但并没有真正测试到它声称要测的内容。此外,16.1.0 还修复了 keystrokeDelay 的 TypeScript 错误以及一个 Service Worker 内存泄漏问题。

升级到 16 后的第一次通过构建,请在 Chrome 中运行,不要只在 Electron 中运行。Electron 仍走传统路径,只在 Electron 中运行根本不会用到原生网络。之后,再对照 Cypress 最佳实践检查你的测试套件。你在 Firefox 和 WebKit 中的测试仍使用 HTTP/1.1,而生产环境中真实的 Firefox 和 Safari 用户使用的是 HTTP/2。因此,借助真实用户的会话回放,可以有效发现 E2E 测试套件从未覆盖到的流程和浏览器。

总结

Cypress 16 带来的大部分提速无需你做任何改动,而它造成的大部分破坏都可以通过搜索代码库找出来。搜索 Cypress.env、cy.exec、cy.end、运行时的 Cypress.config() 调用以及已移除的实验性配置项,按照上表逐一替换,再把 CI 切换到 Node 22 或更高版本并使用 Chrome 运行,然后直接安装 16.1.0 或更高版本。

常见问题

cy.exec() 被移除后,如何在 Cypress 16 中运行 shell 命令?

在 setupNodeEvents 中注册一个 task,在其中调用 Node 的 child_process 模块(例如 execFileSync),然后在测试中通过 cy.task('resetDatabase') 调用它。每个 task 都必须返回一个值或 null。默认情况下,task 在 60 秒后超时,可以通过 taskTimeout 修改这一时限。cy.task() 无法运行永不退出的进程,例如启动服务器。cy.exec() 在 Cypress 15.21.0 中被弃用,并在 16.0.0 中移除。

Cypress 中的 trustedCertificates 和 clientCertificates 有什么区别?

trustedCertificates 是 Cypress 16.1.0 新增的配置项,用于让浏览器信任服务器出示的证书,例如自签名证书或由内部 CA 签发的开发证书。clientCertificates 用于双向 TLS(mTLS),由 Cypress 向服务器出示证书。每个 trustedCertificates 条目只能指定 filePath、pem 或 spki 中的一项,并且只在 Chrome、Chromium 和 Edge 的原生网络路径下生效。配置后,已声明的源即可使用浏览器的 HTTP 缓存。

能在 Cypress 16 上运行 Angular 20 的组件测试吗?

使用内置测试工具不行。Cypress 16 的组件测试不再支持 Angular 18、19 或 20,最低支持版本为 Angular 21.0.0。作为过渡方案,可以从 npm 安装已弃用的 @cypress/angular 4.x 包,并从中导入 mount 来替代 cypress/angular,但 Cypress 已不再维护该工具,因此请尽早规划迁移到 Angular 21。同一版本还移除了内置的 CoffeeScript 支持,.coffee 格式的测试文件、support 文件和 fixture 都将无法再被解析。

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.