3. 无障碍测试工具概览:选对工具,事半功倍

说实话,我刚接触无障碍测试那会儿,一上来就被一堆工具搞懵了。axe-core、Lighthouse、Pa11y、WAVE、Playwright、Cypress……每个都说自己能检测无障碍问题,但到底用哪个?怎么搭?我踩了不少坑才摸清楚门道。这一章我就把这几把“兵器”给你拆开揉碎了讲明白。

无障碍测试工具生态全景 axe-core 核心引擎 检测引擎层 Lighthouse Pa11y WAVE 工具集成层 Playwright Cypress E2E 测试框架层 🚀 全部可集成至 CI/CD Pipeline 本地开发 → 代码提交 → 自动检测 → 生成报告 → 卡点拦截

3.1 先把工具分个类,心里有数

我个人习惯把这六个工具分成三类,这样记起来不乱,选型的时候也更好搭配。

分类 工具 一句话定位
核心检测引擎 axe-core 无障碍检测的“发动机”,几乎所有工具底层都靠它
检测工具集成 Lighthouse / Pa11y / WAVE 把引擎封装成不同场景的检测服务,各有侧重
E2E 测试框架 Playwright / Cypress 在自动化浏览器测试中“顺便”做无障碍断言

💡 记住这个关系:

axe-core 是地基,上面盖什么楼都行。你选工具其实是在选“怎么用”这个引擎。

3.2 逐个盘一盘,都有两把刷子

🔹 axe-core —— 行业标准,绕不开的存在

由 Deque Labs 维护,WCAG 2.1 全覆盖,支持 AA/AAA 级别。为什么说它是标准?因为 Lighthouse、Pa11y 甚至微软的 Accessibility Insights 底层都拿它做检测。我在项目中遇到过好几次:用不同工具测同一页面,结果有出入,最后发现是 axe-core 版本不一致导致的。嗯,版本锁定很重要。

# 命令行直接跑,CI 里最常用的姿势
npx axe https://example.com --save report.json

🛠️ 我的习惯

在 CI 里我会把 axe-core 作为最底层的检测门禁,先过它再过别的。它快、准、误报少,适合做第一道卡点。

🔹 Lighthouse —— 不止无障碍,全维度审计

Chrome 团队出品,集成在 DevTools 里。它把性能、无障碍、SEO、最佳实践打成一个包。我建议你在本地开发时先用它扫一遍,图的是方便——打开 DevTools 点一下就行。但说实话,Lighthouse 的无障碍规则比 axe-core 少一些,而且每次跑的是页面加载快照,动态内容容易漏检。

# CI 里跑 Lighthouse 并输出无障碍报告
lighthouse https://example.com --only-categories=accessibility --output=json --output-path=./lh-report.json

🔹 Pa11y —— 批量扫站,一个顶十个

基于 axe-core 封装,专为批量检测而生。你可以给它一个 URL 列表,它挨个跑并汇总报告。我去年接手一个老项目,2000 多个页面,用 Pa11y 一晚上就跑完了。它支持HTML/CSV/JSON 三种输出,对接 CI 报告系统很方便。

// pa11yci 配置文件示例
{
  "defaults": {
    "standard": "WCAG2AA",
    "timeout": 30000
  },
  "urls": [
    "https://example.com/",
    "https://example.com/login",
    "https://example.com/dashboard"
  ]
}

⚠️ 我曾经踩过的坑

Pa11y 默认的等待策略是 waitForComplete,遇到 SPA 页面容易超时。后来我改成 waitForSelector 指定关键元素,稳定多了。你配置的时候多留意这个参数。

🔹 WAVE —— 可视化标注,设计师也爱用

WebAIM 出品,最大特点是直接在页面上标出问题——红色图标代表错误,绿色代表手动检查项,黄色代表警告。你不用看代码,页面上一目了然。我个人习惯把它作为手动复查的辅助工具,尤其是跟设计师过稿的时候,打开 WAVE 插件一屏展示,沟通效率翻倍。

# WAVE 也支持 API 方式调用
curl -H ": your_key" "https://wave.webaim.org/api/check?url=https://example.com"

🔹 Playwright 与 Cypress —— 把无障碍断言写进 E2E

这两个放一起说,因为思路一样:在浏览器自动化测试里集成 axe-core,每次页面跳转后自动检测无障碍。

Playwright 的生态更开放,我推荐用 @axe-core/playwright 包。它支持 page、locator、iframe 三种作用域,灵活性很高。Cypress 则用 cypress-axe 插件,配合 cy.checkA11y() 命令,写起来很直观。

// Playwright 示例:页面加载后自动执行无障碍检测
import { AxeBuilder } from '@axe-core/playwright';

test('首页无障碍检测', async ({ page }) => {
  await page.goto('https://example.com');
  const results = await new AxeBuilder({ page }).analyze();
  expect(results.violations).toEqual([]);
});

// Cypress 示例
describe('无障碍检测', () => {
  it('登录页应通过 AA 标准', () => {
    cy.visit('/login');
    cy.injectAxe();
    cy.checkA11y(null, { runOnly: { type: 'tag', values: ['wcag2aa'] } });
  });
});

3.3 怎么选?我给个参考组合

你想想看,团队刚起步的时候,不可能六个工具全上。我建议分三个阶段逐步建设:

  1. 第一阶段(1-2周):Lighthouse + axe-core CLI。本地开发随手跑,CI 里做基础卡点。
  2. 第二阶段(1-2月):加入 Pa11y。做全站批量扫描,补齐覆盖率。同时引入 Playwright 或 Cypress 做关键路径的 E2E 无障碍断言。
  3. 第三阶段(持续优化):用 WAVE 做人工抽检和设计师协作,完善报告可视化。

📊 一句话总结工具定位

axe-core 是“发动机”,Lighthouse 是“仪表盘”,Pa11y 是“巡检员”,WAVE 是“透视镜”,Playwright/Cypress 是“警卫员”。各司其职,缺一不可。

3.4 避坑指南:我见过的三个常见问题

  • 规则版本不一致——不同工具可能内置不同版本的 axe-core,导致检测结果打架。解决办法:在 CI 里统一指定 axe-core 版本,用 package.json 锁定。
  • 动态内容漏检——SPA 页面渲染时机不对,工具扫了个空壳。我曾经排查了一下午才发现是 waitFor 时间设短了。建议用 waitForSelector 或 locator.waitFor() 确保 DOM 就绪后再触发检测。
  • 报告太多没人看——CI 里每天生成几百页报告,最后没人打开。我的做法是:只让 violations(违规) 阻断流水线,incomplete(需人工确认) 走通知,passes(通过项) 归档即可。