
测试【免费下载链接】axe-coreAccessibility engine for automated Web UI testing项目地址https://gitcode.com/gh_mirrors/ax/axe-core点击查看免费下载axe-core 是 Deque 出品的自动化 Web 无障碍a11y测试引擎其核心以 JavaScript 实现围绕规则rules、检查checks与虚拟树Virtual Tree展开。本文基于仓库根目录 CONTRIBUTING.md 整理而成面向希望为 axe-core 提交代码的开发者完整覆盖从 CLA 签署、环境搭建、代码规范、目录架构、虚拟节点使用原则、导入边界到单元测试、集成测试、浏览器调试与 TypeScript 类型校验的整套贡献流程。读完本文你将具备独立提交一个符合 axe-core 质量标准的 PR 所需的全部实操能力。一、开始之前签署 CLA 与准备仓库1.1 Contributor License AgreementCLA在向 axe-core 提交任何代码之前必须接受 Contributor License AgreementCLA。贡献者的 CLA 接受情况会被自动检查没有签署 CLA 的 Pull Request 无法被合并。因此第一步应当是先在 cla-assistant 上完成签署再进行后续开发。1.2 Fork 与 Clone贡献流程的标准起点是fork 仓库到自己的账号下再将 fork 后的仓库 clone 到本地。随后需要确认本机已安装 Node.js可从官方渠道下载安装。1.3 使用 pnpm 管理依赖axe-core 使用 pnpm 的packageManager字段固定了期望版本当前为pnpm11.17.0当你在仓库内运行 pnpm 时pnpm 会自动切换到该版本这避免了团队间因 pnpm 版本差异导致的锁文件混乱。基础环境就绪后在仓库根目录依次执行pnpm install pnpm run buildpnpm run build会调用node build/run-build.mjs见 package.json 的build脚本生成最终的axe.js等产物。值得注意的是构建前会先执行prebuild脚本node ./build/check-node-version.mjs校验 Node 版本确保构建环境满足要求。二、代码质量要求Prettier、ESLint 与提交钩子axe-core 虽然没有官方文档化的代码风格指南但维护者会基于现有代码库的水准对 PR 提出修改意见。核心要求是尊重你正在修改的文件的既有编码风格不要因为个人偏好而混入不一致的写法。仓库通过两条工具链保证格式与规范Prettier负责格式化。项目所有.js/.mjs/.md/.json/.ts/.html文件均格式化且每次代码提交commit时都会运行。ESLint负责代码规范。同样在提交时运行也可手动执行pnpm run eslint该命令实际执行的是eslint --color --format stylish {lib,test}/**/*.{js,mjs} build/**/*.mjs doc/**/*.{js,mjs} .github/bin/*.mjs覆盖lib、test、build、doc等核心目录。从 package.json 的lint-staged配置可以看到提交时的具体动作lint-staged: { *.{md,json,ts,html}: [prettier --write], *.{js,mjs}: [prettier --write, eslint --fix] }即文本类文件在提交前自动执行 Prettier 重写JS/MJS 文件则先 Prettier 再 ESLint 自动修复。这意味着不合规的格式在提交阶段就会被拦截你的本地代码需要尽量与之一致避免提交时产生大量自动改动。ESLint 的完整规则定义在 eslint.config.js其中除了通用规则如camelcase、eqeqeq、no-shadow、max-params上限 6、max-depth上限 5 等还包含若干针对 axe-core 特定场景的no-restricted-syntax约束例如禁止使用node.tagName应改用node.nodeName因为 tagName 不适用于所有节点类型禁止直接访问node.attributes该属性可能被 DOM 污染详见 issue #1432应使用node.hasAttributes()或axe.utils.getNodeAttributes(node)禁止使用node.contains()跨 Shadow DOM 无效见 issue #4194应使用axe.utils.contains(node, node2)禁止使用window.HTMLElement/globalThis.HTMLElement不包含 SVG 等全部节点类型应使用window.Node/globalThis.Node。这些约束与下文将要讲的虚拟节点、Shadow DOM 支持原则一脉相承。三、核心概念HTMLElement 与 Virtual Node 的选择这是 axe-core 开发中最关键的一条架构原则直接决定你的代码应放在哪里、怎么写。3.1 什么是 Virtual Tree 与 Virtual Nodeaxe-core 内部维护了一份 HTML 页面的内部副本称为Virtual Tree虚拟树。页面上的每个 HTML 元素都对应一个Virtual Node虚拟节点其作用是在不修改真实 DOM 节点的情况下缓存或规范化关于该元素的信息。虚拟节点的实现位于 lib/core/base/virtual-node/包含三个文件abstract-virtual-node.js抽象基类定义接口virtual-node.js包装真实节点的实现类serial-virtual-node.js用于序列化场景。从 virtual-node.js 的实现可以看到它的设计思路构造函数接收真实节点、父虚拟节点和shadowId并将真实节点保存在actualNode属性中props、attrNames、isFocusable、tabbableElements、clientRects、boundingClientRect、elementInternals等都是带缓存的 getter计算结果存于this._cache避免重复触发昂贵的 DOM 操作attr()/hasAttr()委托给真实节点的getAttribute/hasAttribute对input元素会基于 XHTML 上下文规范化type属性并把非法 type 归一到text。3.2 使用原则能用 Virtual Node 就用在编写规则、检查check、commons 函数时只要可能就应使用 Virtual Node。原因是 Virtual Node 允许 axe-core 缓存计算结果、屏蔽浏览器差异且不会污染真实 DOM。3.3 何时必须使用 HTMLElement但并非所有场景都能用虚拟节点。以下情况必须访问真实 DOM 节点只能通过 DOM API 获取的信息如getRootNode、getBoundingClientRect等任何位于utils 目录lib/core/utils/下的函数不应使用 Virtual Node。3.4 为什么 utils 不能用 Virtual Node理由非常实际使用 Virtual Node 的前提是 axe 已经完成 setup 并创建了 Virtual Tree。而 utils 中的工具函数绝大多数应能在没有 Virtual Tree 存在时独立运行例如在 axe.run 之前、或脱离 axe 状态使用的场景。这一点不是口头约定而是被 ESLint 规则强制执行的。eslint.config.js 中对lib/core/utils/**/*.js设置了no-restricted-syntax禁止在 utils 中出现vNode或virtualNode的成员访问并给出提示Utils is meant for utility functions that work independently of axes state; utilities that require the virtual tree to be set up should go in commons, not utils.从源码结构看setup本身位于 lib/core/public/setup.js它会调用getFlattenedTree生成扁平化虚拟树、调用getSelectorData生成选择器数据并把结果挂在axe._tree上。这也是为什么 utils 目录如 lib/core/utils/ 下的 100 多个文件被定位为无状态、可独立运行的工具集而依赖虚拟树的逻辑应放在commons目录。四、目录结构代码应该放在哪里CONTRIBUTING.md 给出了 axe-core 的完整目录地图以下是结合仓库实际内容整理的结构说明目录职责仓库中的实际位置standardsHTML、WCAG、ARIA 规范的数据对象lib/standards/含 aria-roles.js、html-elms.js、css-colors.js 等core/baseaxe-core 的内部对象结构规则、检查、虚拟节点、审计等lib/core/base/含 audit.js、rule.js、check.js、virtual-node/ 等core/imports来自 Node 模块的 polyfill 或导入lib/core/imports/core/publicaxe 运行与配置的对外函数lib/core/public/含 setup.js 等 19 个文件core/reporters不同 reporter决定一次运行输出哪些数据lib/core/reporters/core/utils无需建立 Virtual Tree 即可运行的工具函数lib/core/utils/commons/aria校验 ARIA 规范、实现 ARIA 计算role、value 等lib/commons/aria/commons/color计算元素前景色/背景色lib/commons/color/commons/dom访问页面、DOM、节点及其视觉状态信息lib/commons/dom/commons/forms表单及其关联输入的处理lib/commons/forms/commons/matches将虚拟节点与特殊 matcher 对象匹配lib/commons/matches/commons/math主要用于 target size 与位置计算的数学函数lib/commons/math/commons/standards从standards查询信息的函数lib/commons/standards/commons/tables数据表格处理lib/commons/tables/commons/text计算元素可访问名称、处理字符串与文本相关属性lib/commons/text/rules每条 axe-core 规则的 JSON 元数据文件及关联的 matches 函数lib/rules/checks每个检查项的 JSON 元数据文件及关联的 evaluate 函数lib/checks/从仓库实例来看lib/rules/下每个规则都由两部分组成*.json元数据如 color-contrast.json与*-matches.js匹配函数如 color-contrast-matches.jslib/checks/下则是*.json如 color-contrast.json与*-evaluate.js如 color-contrast-evaluate.js。了解这一对应关系对定位和修改规则代码至关重要。五、导入边界不同目录能 import 什么CONTRIBUTING.md 明确规定了哪些函数可以被导入、如何导入取决于导入方所在目录。这是 axe-core 架构解耦的核心约束整理如下standards不应使用 import——它们只是硬编码的数据对象。ESLint 中对此有专门约束lib/standards/**/*.js禁止一切 import仅lib/standards/index.js例外。core/utils可通过直接文件路径不走 index 文件导入其他core/utils、core、core/base或standards的函数不得导入 commons/public/checks/rules也不得导入 Node 模块。core/public可通过直接文件路径导入其他core/public或任何core/utils允许导入的内容不得导入 commons/checks/rules。core/imports唯一允许从 Node 模块导入的目录但不应从任何其他目录导入。core/reporters可从core/utils通过index 文件导入。commons可通过直接文件路径导入其他commons或任何core/utils允许的内容通过 index 文件导入不得导入 checks/rules。checks与rules可从任意目录通过index 文件导入。这些边界并非只存在于文档中。eslint.config.js 对上述每个目录都配置了对应的no-restricted-imports规则例如utils 文件禁止导入../commons/、../public/、../checks/、../rules/及 Node 模块public 文件禁止导入../commons/、../checks/、../rules/及 Node 模块imports 文件禁止一切相对路径导入只能导入 Node 模块reporters 文件只能导入 utils 函数commons 文件禁止导入../checks/、../rules/及 Node 模块。也就是说违反导入边界会在 ESLint 阶段直接报错这是贡献者最容易遇到的一类 CI 失败提交前建议先本地运行pnpm run eslint自查。六、Shadow DOM所有改动的前置条件任何涉及规则rules、检查checks、commons 或其他 API 的改动都必须支持开放 Shadow DOMopen Shadow DOM否则不会被接受。这是因为现代 Web 应用中组件化、Shadow DOM 封装已非常普遍axe-core 必须在跨 Shadow 边界的场景下依然正确工作。开发时可参考以下资源doc/API.md可用方法文档doc/developer-guide.md开发指南含测试工具说明test目录下现有测试大量用例展示了如何使用这些 API 处理 Shadow DOM 场景。前文提到的 ESLint 约束如禁止node.contains()改用axe.utils.contains也正是为了规避 Shadow DOM 下的兼容性问题。七、测试要求100% 覆盖与测试文件布局7.1 覆盖率预期axe-core 期望所有代码都被测试 100% 覆盖。仓库虽然没有强制引入覆盖率指标门槛但维护者会人工审查测试并在测试没有充分覆盖代码/改动时提出修改意见。因此提交代码时有测试只是底线测试充分才是标准。7.2 测试文件的位置规则测试应放在test目录下文件路径与文件名与被测源文件保持一致。例如源文件lib/commons/text/sanitize.js对应的测试文件为test/commons/text/sanitize.js源文件 lib/core/utils/ 下的工具函数测试对应在test/core/utils/。这种镜像目录的约定让开发者可以凭路径快速找到任意模块的测试也是 code review 时判断改动是否附带测试的最直观依据。7.3 测试技术栈axe-core 使用Web Test Runner / Mocha / Chai / Sinon作为测试框架组合Web Test RunnerWTR负责在真实浏览器中驱动测试配置见 test/wtr.config.mjsMochaBDD 风格的测试框架提供describe/itChai断言库assert/expect/shouldSinon用于 spy、stub、mock。从 test/wtr.config.mjs 可以看到每个测试页面会统一注入构建产物/axe.js、/tmp/walk-tree.js、chai 与 sinon 的浏览器 bundle以及 test/testutils.js 提供的测试工具如axe.testUtils.registerHooks()注册 mocha 的 beforeEach/afterEach 钩子。浏览器可通过环境变量WTR_BROWSER选择chrome默认无头 Chrome、chrome-debug非无头 9765 端口远程调试、firefox、firefox-nightly。八、文档与注释规范JSDoc 是硬性要求函数必须在其前面附带 JSDoc 风格的注释块说明函数用途、参数与回调。CONTRIBUTING.md 给出的函数注释模板/** * Runs the Audit; which in turn should call run on each rule. * async * param {Context} context The scope definition/context for analysis (include/exclude) * param {Object} options Options object to pass into rules and/or disable rules or checks * param {Function} fn Callback function to fire when audit is complete */类构造函数则应为每个属性附带 JSDoc 注释块。CONTRIBUTING.md 中给出的完整示例对应仓库中的 CheckResult/** * Constructor for the result of checks * param {Object} check CheckResult specification */ function CheckResult(check) { /** * ID of the check. Unique in the context of a rule. * type {String} */ this.id check.id; /** * Any data passed by Check (by calling this.data()) * type {Mixed} */ this.data null; /** * Any node that is related to the Check, specified by calling this.relatedNodes([HTMLElement...]) inside the Check * type {Array} */ this.relatedNodes []; /** * The return value of the Checks evaluate function * type {Mixed} */ this.result null; }遵循这一规范不仅便于维护也保证 JSDoc 生成的 API 文档pnpm run api-docs质量。九、开发与测试命令全览9.1 构建前置条件运行 axe 测试前必须先用pnpm run build生成axe.js。所有单元测试、集成测试都依赖构建产物。9.2 单元测试运行全部单元测试pnpm test注意pnpm test实际执行的是pnpm run test:tsc run-s test:unit:* -- {} --即先做 TypeScript 类型检查再串行运行所有test:unit:*子任务。持续开发模式监听源码变化、自动重构建并重跑相关测试pnpm run develop该命令监听lib/与build/的改动当 9876 端口空闲时启动 http-server并重跑相关测试。9.3 集成测试与其他 CI 测试pnpm run test:integrationtest:integration实际指向test:integration:chrome即用start-server-and-test先起 9876 端口服务器再运行基于 Selenium WebDriver 的完整集成测试Chrome 浏览器。还可用test:integration:firefox在 Firefox 上运行。另有几个在 CI 过程中运行的测试# 使用当前本地构建的 axe.js 运行 doc/examples/* 中的示例测试 pnpm run test:examples # 运行 test/node 下的 Node 环境测试 pnpm run test:node9.4 运行与调试指定单元测试不需要跑全量单元测试时可按目录精准执行# 仅运行 test/core pnpm run test:unit:core # 仅运行 test/commons pnpm run test:unit:commons # 仅运行 test/rule-matches pnpm run test:unit:rule-matches # 仅运行 test/checks pnpm run test:unit:checks # 仅运行 test/integration/rules规则集成测试 pnpm run test:unit:integration # 仅运行 test/integration/apiAPI 集成测试 pnpm run test:unit:api # 仅运行 test/integration/virtual-rules虚拟规则测试 pnpm run test:unit:virtual-rules这些命令均通过web-test-runner --config test/wtr.config.mjs --files ...实现与 test/wtr.config.mjs 中的默认文件列表test/core/**、test/commons/**、test/checks/**、test/rule-matches/**、test/integration/api/**、test/integration/virtual-rules/**、test/gather-internals/**、tmp/integration-tests/**对应。在浏览器中调试单元测试pnpm run test:debug该命令启动 Web Test Runner 服务器--manual手动模式。按D键可打开 Chrome 浏览器点击测试链接即可开始调试你可以使用浏览器自带的调试器也可以在 9765 端口附加外部调试器文档提及仓库提供了 VS Code launch 配置注意部分镜像仓库可能不包含.vscode目录。由于测试规模很大建议只调试特定测试集而非整套。使用files参数传入 glob 模式pnpm run test:debug -- --files test/core十、TypeScript 支持axe.d.ts 与类型测试10.1 类型定义文件axe-core 的类型定义文件随模块一起分发位于仓库根目录 axe.d.ts目前支持 TypeScript 2.0。类型定义测试可运行pnpm run test:tsc该命令执行tsc见 package.json 的test:tsc脚本使用 tsconfig.json 检查类型正确性。10.2 在自己的 TypeScript 测试中使用 axe在你的 TypeScript 项目中引入 axe 进行无障碍测试非常简单import * as axe from axe-core; describe(Module, () { it(should have no accessibility violations, done { axe.run(compiledFixture).then(results { expect(results.violations.length).toBe(0); done(); }, done); }); });axe.run返回 Promiseresults.violations是违规项数组。axe-core 的完整类型定义含AxeResults、Rule、Check等接口都在 axe.d.ts 中可自行查阅。十一、调试只在 CircleCI 上失败的测试当某个测试只在 CircleCI 失败、本地无法复现时可通过 X11 转发在本地查看 CI 中的浏览器画面在本地安装 X-Windows 客户端如 XQuartz在 CircleCI 界面选择 Retry the build with SSH enabled获取 SSH 连接命令为 SSH 命令添加-X标志启用 X11 转发例如ssh -X -p 64605 ubuntu13.58.157.61登录后设置显示环境并启动 Chromeexport DISPLAYlocalhost:10.0 /opt/google/chrome/chrome如果遇到.Xauthority does not exist错误编辑并保存~/.Xauthority文件即可vi ~/.Xauthority :wq另开一个 SSH 终端不加-X启动开发服务器cd axe-core pnpm run develop然后在 XQuartz 打开的 Chrome 中加载测试文件 URL即可实时观察 CI 环境中的失败现场。十二、提交与 PR 的配套规范代码质量之外提交规范同样重要。CONTRIBUTING.md 指向了更详细的 doc/code-submission-guidelines.md要点包括遵循Angular commit message 风格格式为type(scope): subjecttype 可为feat/fix/docs/style/refactor/perf/test/chore/cisubject 使用祈使句、首字母小写、结尾不加句号整条消息不超过 100 字符提交信息会被用于生成 CHANGELOG.md因此规范性直接影响发布文档质量影响规则rule的改动必须附带集成测试在test/integration/rules对应的 HTML 中新增测试元素并给出唯一id同时在同名 JSON 文件的violations或passes数组中登记该 id注意 id 要放在数组中因为它们是 axe-core 选择器支持 iframe 嵌套结构PR 合入前通常需要 rebase 到origin/develop并将多个 commit 压缩为一个避免引入 merge 提交且任何情况下都不得 force push 到 develop 或 master。结语为 axe-core 贡献代码本质上是进入一套围绕可维护性、可测试性、架构边界精心设计的工程体系虚拟节点与真实 DOM 的取舍、utils 与 commons 的职责划分、目录级导入边界、Shadow DOM 兼容性、镜像目录的测试布局每一步都有文档约定与 ESLint 规则双重保障。按本文的流程搭建环境、理解架构、编写符合规范的代码与测试再通过pnpm run eslint、pnpm test等命令完成本地验证你的 PR 就能以最小的沟通成本进入 review 流程。赞分享测试【免费下载链接】axe-coreAccessibility engine for automated Web UI testing项目地址https://gitcode.com/gh_mirrors/ax/axe-core点击查看免费下载相关推荐OceanBase 贡献者开发指南从环境搭建、源码构建到编码规范与调试测试的完整实践OceanBase 贡献者开发指南从环境搭建、源码构建到编码规范与调试测试的完整实践 导读 本文是 OceanBase 开源仓库中英文开发指南 docs/d数据库分布式数据库关系型数据库后端高可用Moto 贡献者开发环境安装与测试指南从本地虚拟环境到 Devcontainer 的完整实践Moto 贡献者开发环境安装与测试指南从本地虚拟环境到 Devcontainer 的完整实践 导读 Moto 是一个用于模拟 AWS 基础设施、帮助开发者编写Mock测试pdf-lib 贡献指南从环境搭建到单元/集成测试、编译与调试的完整实践pdf lib 贡献指南从环境搭建到单元/集成测试、编译与调试的完整实践 pdf lib 是一个致力于“在任何 JavaScript 环境中创建与修改 PDF开发工具上一篇AI-Infra-Guard × DeepSeek Harness 间接提示注入受控评估实验矩阵、安全复现设计与双评测器结果下一篇Flip-Card低功耗优化实战从2天到7天续航的嵌入式电源管理技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考