ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Gatsby 端到端测试完整指南:基于 Cypress 的 E2E 测试实践与源码原理解析

2026/9/19 3:41:13 拓冰建站 浏览量
Gatsby 端到端测试完整指南:基于 Cypress 的 E2E 测试实践与源码原理解析 Gatsby 端到端测试完整指南基于 Cypress 的 E2E 测试实践与源码原理解析【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby导读本文基于 Gatsby 官方文档《End-to-End Testing》仓库路径docs/docs/how-to/testing/end-to-end-testing.md系统讲解如何为 Gatsby 站点搭建以 Cypress 为核心的端到端E2E测试体系。你将掌握从环境安装、start-server-and-test串联开发服务器与测试、编写可访问性断言到 CI 流水线中基于gatsby build/gatsby serve的完整生产级测试方案同时结合本仓库中gatsby-cypress包与api-runner-browser.js的源码理解CYPRESS_SUPPORT、waitForRouteChange()等 Gatsby 专属测试能力的底层原理。除 Cypress 外Playwright 也是与 Gatsby 配合良好的备选方案但本文聚焦 Cypress。前置条件在开始之前请确保你的项目满足以下条件一个已有的 Gatsby 站点。如果你还没有可参考 Quick Start 从零创建。TypeScript作为 devDependency 安装用于编写类型安全的测试与配置文件npm install --save-dev typescript安装三个核心测试依赖cypress、start-server-and-test与gatsby-cypressnpm install --save-dev cypress start-server-and-test gatsby-cypresscypress端到端测试框架本体start-server-and-test负责先启动开发服务器、等待端口就绪后再运行 Cypress 的进程编排工具gatsby-cypress为 Cypress 注入 Gatsby 专属命令的官方辅助包非必需仅提供便利命令。本仓库中有一个可直接对照的完整示例examples/using-cypress一个演示用 Cypress axe 编写可访问性测试的 Gatsby 示例站点。其 package.json 的 devDependencies 中即包含testing-library/cypress、axe-core、cypress、cypress-axe、gatsby-cypress、start-server-and-test与typescript的完整组合可作为你的依赖清单模板。初始配置在创建好 Cypress 配置文件之后你将使用start-server-and-test把 Gatsby 开发服务器与 Cypress 串联起来运行。1. 创建 Cypress 配置文件在项目根目录创建cypress.config.ts用于设置cy.visit()的默认 URL 前缀以及测试文件所在目录import { defineConfig } from cypress export default defineConfig({ e2e: { baseUrl: http://localhost:8000, specPattern: cypress/e2e } })配置完成后所有cy.visit()调用都会默认加上http://localhost:8000前缀例如cy.visit(/)实际访问的是http://localhost:8000/。这与gatsby develop的默认端口8000一致。本仓库示例 examples/using-cypress/cypress.config.ts 正是此配置的完整落地。2. 添加test:e2e脚本在package.json中添加脚本以便一键同时启动 Gatsby 与 Cypress{ scripts: { develop: gatsby develop, cy:open: cypress open --browser chrome --e2e, test:e2e: CYPRESS_SUPPORTy start-server-and-test develop http://localhost:8000 cy:open } }执行流程说明CYPRESS_SUPPORTy环境变量会在 Gatsby 内部启用测试工具钩子其底层机制见下文源码原理解析一节start-server-and-test develop http://localhost:8000 cy:open会先执行develop即gatsby develop持续探测http://localhost:8000是否可用就绪后再执行cy:open打开 Cypress 交互式测试运行器。3. 初始化 Cypress 项目运行npm run test:e2e即test:e2e脚本Cypress 会在首次启动时生成cypress/目录骨架含e2e/、support/、fixtures/等。4. 引入gatsby-cypress命令在cypress/support/e2e.ts中引入 Gatsby 专属命令import gatsby-cypress/commands如果使用 TypeScript还需在 Cypress 的cypress/tsconfig.json中声明类型以获取waitForRouteChange、waitForAPI等命令的类型提示类型声明见 packages/gatsby-cypress/index.d.ts{ compilerOptions: { types: [cypress, gatsby-cypress] }, include: [.] }完成以上初始化后你就可以在gatsby develop模式下快速迭代测试。若希望验证生产构建同样通过测试请阅读下文持续集成CI一节。使用--https标志时的注意事项如果你使用gatsby develop --https启动开发服务器无论使用自签名还是自动生成的证书必须告知start-server-and-test关闭 HTTPS 证书校验否则它会一直等待端口就绪而永远无法启动 Cypress。通过环境变量START_SERVER_AND_TEST_INSECURE1解决{ scripts: { test:e2e: START_SERVER_AND_TEST_INSECURE1 CYPRESS_SUPPORTy start-server-and-test develop http://localhost:8000 cy:open } }编写测试Cypress 本身的完整语法不在本文范围内建议阅读 Cypress 官方文档《Writing your first E2E test》学习。此外官方推荐安装testing-library/cypress以获得findByText、findAllByText等更符合用户视角的元素查询匹配器。测试可访问性自动化端到端测试的一个典型高质量场景是用cypress-axe断言可访问性——它是把 axe 可访问性检测 API 接入 Cypress 的插件。虽然良好的 Web 可访问性仍需要一定的人工测试但自动化能显著减轻测试人员的负担。第一步安装依赖包npm install --save-dev cypress-axe axe-core testing-library/cypress第二步在cypress/support/e2e.ts中注册命令import gatsby-cypress/commands import cypress-axe import testing-library/cypress/add-commands第三步编写可访问性测试describe(Accessibility tests, () { beforeEach(() { cy.visit(/).waitForRouteChange().get(main) cy.injectAxe() }) it(Has no detectable accessibility violations on load, () { cy.checkA11y() }) it(Navigates to page 2 and checks for accessibility violations, () { cy.findByText(/go to page 2/i) .click() .waitForRouteChange() .checkA11y() }) it(Focuses on the footer link and asserts its attributes, () { cy.findAllByText(Gatsby).focus() cy.focused() .should(have.text, Gatsby) .should(have.attr, href, https://www.gatsbyjs.com) .should(not.have.css, outline-width, 0px) }) })测试要点拆解beforeEach中cy.visit(/)后紧跟.waitForRouteChange()确保 Gatsby 完成路由切换、事件处理器就绪后再get(main)避免竞态随后cy.injectAxe()把 axe-core 注入当前页面第一个用例在页面加载后调用cy.checkA11y()断言无可见可访问性违规第二个用例通过cy.findByText(/go to page 2/i)找到链接、点击等待路由切换完成后再次checkA11y()覆盖页面间导航后仍无障碍违规的断言第三个用例验证焦点管理聚焦页脚链接后断言其文本、href属性并断言焦点可见outline-width不为 0px这是键盘可访问性的自动化验证。更多示例可查阅 cypress-axe 官方文档以及本仓库的 examples/using-cypress/cypress/e2e/accessibility.cy.ts 和 smoke.cy.ts。Gatsby 专属 Cypress 命令与源码原理本文原文档重点依赖的gatsby-cypress包位于仓库 packages/gatsby-cypress核心实现集中在 src/commands.js 与 src/api-handler.js。引入gatsby-cypress/commands后你会获得如下命令命令说明示例cy.waitForRouteChange()等待 Gatsby 完成路由切换确保事件处理器正确挂载cy.visit(/page-2).waitForRouteChange()cy.waitForAPI(api-name)等待某个 Gatsby API 执行完成cy.waitForAPI(onRouteUpdate).get(#element-with-event-handler).click()cy.waitForAPIorTimeout(api-name)等待 API 完成超时则继续用于防止测试永久挂起cy.waitForAPIorTimeout(onRouteUpdate)cy.getTestElement(selector)按data-testid属性选择元素旧命令v6 起计划移除cy.getTestElement(my-element)底层原理CYPRESS_SUPPORT与 API 钩子waitForRouteChange本质上是对waitForAPI(onRouteUpdate)的封装见 src/commands.js即等待 Gatsby 浏览器端onRouteUpdate生命周期执行完毕。它的运行依赖CYPRESS_SUPPORT环境变量开启的测试钩子在构建端Gatsby 的 webpack.config.js 会把process.env.CYPRESS_SUPPORT序列化注入浏览器环境在浏览器端packages/gatsby/cache-dir/api-runner-browser.js 的apiRunner每次分发生命周期 API 前会检查process.env.CYPRESS_SUPPORT若已开启则调用window.___apiHandler(api)若存在否则把 API 名推入window.___resolvedAPIs数组src/api-handler.js 维护了等待-完成状态机测试侧调用waitForAPI(api)时创建一个 Promise 并记录awaitingAPI若该 API 已被标记为pre-resolved即测试注册时 API 已先执行完则立即 resolve否则等apiRunner回调apiHandler命中awaitingAPI时再 resolve。这套机制保证了测试可以精确对齐 Gatsby 的运行时生命周期避免在路由尚未切换完成、事件监听尚未挂载时就断言元素从而消除 E2E 测试中最常见的竞态问题。waitForAPIorTimeout则在 30 秒默认TIMEOUT 30000见 src/commands.js内等待 API超时后通过Promise.race继续执行防止 CI 因个别 API 未触发而无限挂起。注意根据 packages/gatsby-cypress/README.md 的说明gatsby-cypress并非使用 Cypress 的必要依赖它仅为便利而提供上述命令。若你更倾向于用testing-library/cypress按文本/标签/data-testid选择元素完全可以不引入它。持续集成CI在 GitHub Actions、CircleCI 等 CI 环境中运行 Cypress 时必须使用cypress run无头运行而不是cypress open交互式运行器。同时为了最大程度贴近线上生产环境应使用gatsby buildgatsby serve而非开发服务器。在package.json中配置如下{ scripts: { build: gatsby build, serve: gatsby serve, cy:run: CYPRESS_baseUrlhttp://localhost:9000 cypress run --browser chrome, test:e2e:ci: CYPRESS_SUPPORTy npm run build start-server-and-test serve http://localhost:9000 cy:run } }执行流程说明CYPRESS_SUPPORTy npm run build以启用测试钩子的方式执行生产构建start-server-and-test serve http://localhost:9000 cy:run用gatsby serve默认端口 9000托管生产构建产物就绪后运行无头测试cy:run中通过CYPRESS_baseUrlhttp://localhost:9000环境变量覆盖默认baseUrl使测试指向生产预览地址。在你的 CI 配置中运行test:e2e:ci脚本即可。本仓库示例 examples/using-cypress/package.json 中完整包含上述两套脚本开发模式test:e2e与 CI 模式test:e2e:ci可直接对照。关于 CI 的更多选项如自定义 Cypress 配置、并行化、缓存等可阅读 Cypress 官方《CI Introduction》。例如若不想用CYPRESS_baseUrl环境变量修改baseUrl也可以为 CI 单独定义一个 Cypress 配置文件在 CI 脚本中通过--config-file指定它来代替默认配置。附加资源Cypress 官方文档Playwright 官方文档gatsby-cypress 包说明仓库内 READMEcypress-axe 文档仓库内可直接参考的完整示例examples/using-cypress含 cypress 配置、可访问性测试、TypeScript 支持与 CI 脚本【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考