3. 无障碍测试工具概览:选对工具,事半功倍
说实话,我刚接触无障碍测试那会儿,一上来就被一堆工具搞懵了。axe-core、Lighthouse、Pa11y、WAVE、Playwright、Cypress……每个都说自己能检测无障碍问题,但到底用哪个?怎么搭?我踩了不少坑才摸清楚门道。这一章我就把这几把“兵器”给你拆开揉碎了讲明白。
3.1 先把工具分个类,心里有数
我个人习惯把这六个工具分成三类,这样记起来不乱,选型的时候也更好搭配。
💡 记住这个关系:
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-2周):
Lighthouse + axe-core CLI。本地开发随手跑,CI 里做基础卡点。 - 第二阶段(1-2月):加入
Pa11y。做全站批量扫描,补齐覆盖率。同时引入Playwright或Cypress做关键路径的 E2E 无障碍断言。 - 第三阶段(持续优化):用
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(通过项) 归档即可。