ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Gutenberg 仓库测试实战指南:Jest / PHPUnit / Playwright 三类测试的编写、运行与调试规范

Gutenberg 仓库测试实战指南:Jest / PHPUnit / Playwright 三类测试的编写、运行与调试规范 Gutenberg 仓库测试实战指南Jest / PHPUnit / Playwright 三类测试的编写、运行与调试规范【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenbergGutenberg 仓库同时承载 PHP 与 JavaScript 代码对应的测试体系也分为三条主线JavaScript 单元/集成测试Jest Vitest、PHP 测试PHPUnit与端到端测试Playwright。本篇基于仓库内的.agents/skills/testing/SKILL.md技能文档及其三个分类参考references/jest.md、references/php.md、references/e2e.md结合 docs/contributors/code/testing-overview.md 等仓库文档系统讲解在 Gutenberg 中编写、运行、调试与维护测试的完整工作流先规划、再编码、按类型路由、守住不削弱测试、不靠改生产代码凑通过的底线。读完后你将能独立为任意改动补充合理的单测、集成测试或 e2e 测试并正确运行与排查它们。一、三条测试主线的全景Gutenberg 的测试体系在仓库根目录 package.json 的 scripts 中集中注册整体可分为测试类型框架运行命令环境依赖JavaScript 单元/集成测试Jest迁移中部分归 Vitestnpm run test:unit/npm run test:unit:vitest无需 wp-envPHP 测试PHPUnitcomposer test或vendor/bin/phpunit需要 wp-env 测试环境端到端测试E2EPlaywrightnpm run test:e2e需要 wp-env 测试环境npm test会一次性执行全部 JS 单元测试、Vitest 测试与代码 lint见 package.json 中test: npm run lint npm run test:unit npm run test:unit:vitestnpm run test:php则执行 PHP lint 加 PHPUnit 测试。由于 Jest 到 Vitest 的迁移正在进行运行全部 JS 单测需要同时执行npm run test:unit与npm run test:unit:vitest。二、先规划后动手测试编写的工作流纪律.agents/skills/testing/SKILL.md的第一条规则也是整个工作流的起点在写任何测试体之前先与作者确认测试清单。以从用户视角描述行为的方式起草测试名称一个用例只覆盖一种行为具体命名规范见下文描述测试一节每个提议的用例必须能追溯到本次新增或变更的行为不要为凑数量而填充相邻或无关的覆盖若在无人值守 unattended模式下工作应把建议清单写入工作摘要供后续 review。随后是两条不可逾越的红线绝不通过削弱测试来让失败测试变绿不放松断言、不加多余的等待或超时、不静默跳过用例。遇到失败必须诊断根因或如实上报失败。绝不通过修改生产代码来让失败测试通过除非生产代码本身就是 bug 的根源e2e 测试通过不是任务成功的最终标准核心目标是验证生产代码符合预期行为。这两条红线保证了测试驱动修改而非测试被测试倒逼是仓库测试文化中最关键的部分。三、JavaScript 单元与集成测试Jest / Vitest对应参考文件 references/jest.md。3.1 运行方式# 运行指定目录下的全部单测 npm run test:unit path_to_test_directory # 按测试名称过滤运行支持正则 npm run test:unit -- --testNamePatternTestName # 运行全部 JS 测试并附带 lint包含 Vitest 部分 npm testJest 单测不需要 wp-env纯 Node 环境即可执行Vitest 迁移期间Jest 掌管的 JSDOM 测试用npm run test:unitVitest 掌管的测试用npm run test:unit:vitest。3.2 文件夹结构与导入约定测试文件放在与源码同目录的test/子目录中且测试文件名与被测文件同名如bar.js的测试位于test/bar.js只允许含至少一个用例的测试文件直接位于test/下外部 mock 与 fixture 放入子目录例如test/mocks/[file-name].js、test/fixtures/[file-name].js导入被测代码时优先使用相对路径import { bar } from ../bar;避免使用工程级路径import { bar } from components/foo/bar;便于代码迁移。文件名后缀决定运行环境*.jsdom.test.*面向 DOM 结构、语义、事件、状态等确定性行为*.browser.test.*面向样式计算、布局、可见性、焦点顺序、动画、滚动、媒体查询等依赖浏览器渲染的行为。Node 兼容的测试不加环境后缀由文件名自动选择环境。3.3 描述测试从用户视角命名describe块用于分组每个用例尽量只描述一种行为。命名描述的是用户可见的期望行为而非代码内部实现// 推荐从用户视角描述行为 describe( CheckboxWithLabel, () { test( checking checkbox should disable the form submit button, () { // ... } ); } ); // 不推荐描述内部实现细节 describe( CheckboxWithLabel, () { test( checking checkbox should set this.state.disableButton to true, () { // ... } ); } );3.4 Setup / teardown 与 mockJest 的beforeAll/afterAll/beforeEach/afterEach支持异步代码返回 Promise 即可等待。清理代码应放在这些钩子里不要放在断言之后——否则断言失败时清理不会执行可能污染其他用例。Mock 分两条路线依赖注入把依赖作为函数参数传入function isValueValid( value, validValuesList [] )测试时可注入 mock 列表并顺手覆盖更多边界场景jest.mock打桩对散布在多处的导入依赖用jest.mock替换模块并配合jest.fn()控制返回值全局方法用jest.spyOn( global, open ).mockImplementation( () true )之类的 spy 验证全局调用。3.5 用户交互测试优先 user-event模拟用户交互推荐使用testing-library/user-event而不是底层的fireEvent。fireEvent只派发测试脚本中写明的事件可能与真实浏览器交互不符而user-event会按真实交互派发完整事件序列focus、pointer、mouse、click、keydown/keypress/keyup、change 等并处理 React 特有的细节import { render, screen } from testing-library/react; import userEvent from testing-library/user-event; test( fires onChange when a new value is typed, async () { const user userEvent.setup(); const spyOnChange jest.fn(); render( MyComponent onChange{ spyOnChange } / ); const input screen.getByRole( textbox ); await user.clear( input ); // 聚焦并清空 await user.type( input, 62 ); // 逐字符输入产生完整键盘事件 expect( spyOnChange ).toHaveBeenCalledTimes( 3 ); // clear()、6、62 const select screen.getByRole( listbox ); await user.selectOptions( select, [ optionValue ] ); } );3.6 块级 UI 集成测试优先于 e2ereferences/jest.md特别强调块级 UI 优先写集成测试而非 e2e——集成测试在真实的 block editor 实例中渲染组件更快也更稳定。它们随单测命令运行通过文件名选择 jsdom 或 Browser Mode 环境。集成测试的核心 helper 是 test/integration/helpers/integration-test-editor.jsx 中导出的initializeEditor它返回testing-library/react的render结果并支持传入多块元数据数组以搭建多块编辑场景import { initializeEditor } from test/integration/helpers/integration-test-editor; async function setup( attributes ) { const testBlock { name: core/cover, attributes }; return initializeEditor( testBlock ); }该 helper 还导出selectBlock可按块外层 aria-label如 Block: Cover选中被测块。依赖浏览器渲染或原生输入的行为使用 Browser Mode只有需要完整 WordPress 站点或页面间跳转的行为才保留为 e2e 测试。四、PHP 测试PHPUnit对应参考文件 references/php.md。PHP 测试必须依赖 wp-env 测试环境。4.1 环境准备与运行# 先检查 wp-env 测试环境是否已在运行 npm run wp-env-test status # 仅当未运行时才启动 npm run wp-env-test start # 运行全部 PHP 测试 composer test # 运行指定文件或目录 vendor/bin/phpunit path_to_test_file.php仓库根目录的 composer.json 定义了testphpunit与test:watchphpunit-watcher watch脚本phpunit.xml.dist 配置了 bootstrapphpunit/bootstrap.php、-test.php后缀的测试目录./phpunit/、./phpunit/tests/、./phpunit/blocks/以及排除组如ms-required、fontsapi。若使用内置本地环境也可直接npm run test:phpPHP lint 测试或npm run test:unit:php仅测试不含 lint。4.2 测试带前缀的函数关键坑点Gutenberg 的构建系统会自动为 PHP 函数加gutenberg_前缀、为类加_Gutenberg后缀以避免与 WordPress Core 冲突。因此PHPUnit 测试必须调用构建后的带前缀版本而不是源码版本// phpunit/blocks/my-block-test.php class My_Block_Test extends WP_UnitTestCase { public function test_my_function() { // 测试构建后的函数带 gutenberg_ 前缀 $result gutenberg_block_core_my_block_render_function( $args ); $this-assertEquals( $expected, $result ); } public function test_my_class() { // 测试构建后的类带 _Gutenberg 后缀 $handler new WP_Example_Block_Handler_Gutenberg(); $result $handler-process( $input ); $this-assertEquals( $expected, $result ); } }若测试被回迁backport到 WordPress Core则需改回测试不带前缀的版本。构建系统与前缀机制的完整说明见 docs/contributors/code/build-system-function-prefixing.md。五、端到端测试Playwright对应参考文件 references/e2e.md 与仓库规范 docs/contributors/code/e2e/README.md。E2E 测试同样依赖 wp-env。5.1 编写流程先读 End-to-End 指南docs/contributors/code/e2e/README.md掌握 locator、Page Object Model、断言与跨浏览器标签约定在此之前不要动笔检查已有 spec在test/e2e/specs/area/下查找是否已有覆盖该区域的 spec尽量扩展既有文件而非另建平行文件为确认的清单写完全部用例体某个用例若不可行要明说不能默默省略验证scoped headless 下通过并重复运行确认稳定npm run test:e2e -- path_to_spec --repeat-each35.2 运行约束保持 headless默认行为不使用--headed、--ui、--debug——这些是给人用的调试选项会打开 GUI 阻塞 Agent 会话运行 scoped 子集npm run test:e2e -- path_to_test_file.spec.js只跑受改动影响的 spec。完整套件耗时很长若被要求无范围地跑全部 e2e先确认哪些 spec 相关无人值守时收敛到受影响区域并在摘要中说明单个文件、指定浏览器--projectchromium|firefox|webkit、--headed与--debug等完整命令清单见 docs/contributors/code/e2e/README.mdLinux 下 WebKit 需 headed 模式无图形界面时用xvfb-run前置。5.3 Fixtures 与编辑器画布Fixtures 使用 packages/e2e-test-utils-playwright/README.md 中的wordpress/e2e-test-utils-playwright它扩展了 Playwright 的test模块注入四个 fixtureadmin访问后台页面等、editor块编辑器工具、pageUtils通用页面工具、requestUtilsREST 请求工具。编辑器画布是 iframe 的必须通过editor.canvas与画布内元素交互。5.4 选择器与断言规范禁止$等返回 ElementHandle 的 API$、$$、$eval、$$eval一律使用惰性的Locator可配合 Playwright 断言优先可访问选择器getByRole不依赖内部实现page.getByRole( button, { name: Hello World } ); page.getByRole( region, { name: Block Library } ) .getByRole( option, { name: Buttons } );选择器默认严格模式一次查询命中多个元素会直接抛错简单工具函数直接内联特定页面复用逻辑用Page Object Model如PageUtils本身就是 POM通过this互相引用复杂且跨页面重复的动作才抽成 util状态清理优先走 API用requestUtils.rest/requestUtils.batchRest调 REST 接口设置/清除状态避免手工慢操作手工设置流程只需单独测一次显式断言如点击前先expect( locator ).toBeVisible()让测试流程更易读。5.5 跨浏览器标签默认只在 chromium 运行在测试标题任意位置写浏览器名即可额外在对应浏览器运行-chromium可关闭默认浏览器test( I will run in firefox and webkit (and chromium by default), async ( { page } ) {} ); test( I will only run in firefox but not -chromium, async ( { page } ) {} ); test.describe( Grouping tests (webkit, -chromium), () { test( I will only run in webkit, async ( { page } ) {} ); } );六、快照测试用法、更新与风险快照是测试生成并提交到仓库的数据结构表示运行时与文件对比。快照适合组件结构与 reducer 等大型复杂数据结构的回归保护也适合重构——沿提交历史维护的快照 diff 可以记录组件结构的演化。6.1 创建与更新快照由测试生成永远不要手工创建或修改。破坏性变更需要更新快照按运行器选择命令# Vitest 掌管的 Node / DOM 测试 npm run test:unit:vitest:update -- path/to/tests # Jest 掌管的 JSDOM 测试--testPathPatterns 可选只跑匹配测试 npm run test:unit:update -- --testPathPatterns path/to/tests # e2e 快照 npm run test:e2e -- --update-snapshots path/to/spec开发时可保持 watch 常驻npm run test:unit:vitest:watch -- path/to/tests或npm run test:unit:watch -- --testPathPatterns path/to/tests快照失败时按u即可更新。6.2 最佳实践与痛点快照本身不表达期望应与其他显式断言并用如快照外再补expect( screen.getByText( /mars/i ) ).toBeInTheDocument()toMatchDiffSnapshot只对两个 DOM 状态之间的差异生成快照适合验证 prop 变化对 DOM 的影响快照体积更小非确定性的测试随机、时间相关不适合快照connected 组件快照需导出未 connect 的组件并手工提供 connected props样式类断言在 Browser Mode 用getComputedStyle等窄范围断言验证浏览器真实结果并手动 import 断言所依赖的全局样式表Browser Mode 不会自动加载 WordPress enqueue 的 Sass。七、稳定性与疑难排查7.1 复现 CI 中的偶发失败节流模拟E2E 本地通过但 CI 失败往往是 CPU 或网络竞态。可用环境变量模拟慢速环境详见 docs/contributors/code/testing-overview.md 的 Scenario testing 一节THROTTLE_CPU4 npm run test:e2e # 4 倍 CPU 降速 SLOW_NETWORKtrue npm run test:e2e # 模拟 Fast 3G OFFLINEtrue npm run test:e2e # 模拟断网7.2 Flaky 测试的识别与上报测试在无代码变更的情况下多次重试间有通过有失败即视为flaky。CI 对失败测试最多自动重试两次以侦测并由report-flaky-tests动作把 flaky 测试及错误汇总为 PR 上的单条评论实现见 packages/report-flaky-tests/README.md。连续失败三次不视为 flaky也不会被上报且 flaky 只在 PR 上报告。7.3 调试单测npm run test:unit:debug会以调试模式启动测试可用 Node inspector 客户端Chrome DevTools 或 VS Code附加并逐步检查执行过程详细指引见 packages/scripts/README.md 中 Debugging Jest unit tests 一节。八、性能测试补充性能测试本质是基于 e2e 的指标采集监控编辑器加载时间、输入响应时间、块选择时间等关键指标。准备环境nvm use npm install npm run build后npm run test:performance # 当前分支/代码的结果 npm exec --no release-cli -- perf trunk v8.1.0 v8.0.0 # 跨分支对比 npm exec --no release-cli -- perf trunk v8.1.0 v8.0.0 --tests-branch add/perf-tests-coverage--tests-branch指定要运行的性能测试文件所在分支适合修改/扩展 perf 测试时使用。基准测试期间应尽量不操作电脑减少外部因素对跨分支对比的影响。九、落地清单给贡献者的一份速查先规划向作者确认测试清单一个用例一种行为全部可追溯到本次行为变更无人值守时写入摘要再选型块级 UI 优先集成测试initializeEditor依赖完整站点/页面跳转才用 e2e确定性 DOM 行为用 jsdom样式/布局/焦点类用 Browser ModePHP 用 PHPUnit严守红线不削弱测试、不加 wait 蒙混、不静默跳过e2e 通过 ≠ 任务完成除非生产代码本身有 bug 否则不改它正确运行JS 用npm run test:unittest:unit:vitest无需 wp-envPHP 与 e2e 先npm run wp-env-test status再starte2e 永远 scoped headless--repeat-each3验证稳定注意细节PHP 测带gutenberg_前缀/_Gutenberg后缀的构建产物e2e 用getByRole、Page Object Model、requestUtils.rest清状态、editor.canvas操作 iframe 画布快照变更走*:update命令而非手改。沿着这条工作流无论是新增一个核心块、调整编辑器 UI 还是修复 PHP 渲染逻辑都能在正确的层级用正确的工具完成验证并让每个测试成为可维护、可追溯的行为契约。延伸阅读docs/contributors/code/testing-overview.md全部测试类型的权威总览 docs/contributors/code/e2e/README.md 与 docs/contributors/code/e2e/overusing-snapshots.mdE2E 最佳实践与快照滥用警示 docs/contributors/code/build-system-function-prefixing.mdPHP 前缀机制 packages/e2e-test-utils-playwright/README.mdE2E fixtures 与 API。【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表