前端可访问性:自动化测试工具与实践指南
前言
各位前端小伙伴,今天咱们来聊聊可访问性的自动化测试。想象一下:
- 你开发了一个功能丰富的网站
- 手动测试时觉得一切正常
- 但发布后发现有很多可访问性问题
- 用户投诉不断
自动化测试可以帮助我们在开发过程中及时发现问题。今天咱们就来学习主流的可访问性测试工具和实践!
自动化测试工具概览
工具对比
| axe-core | JavaScript库 | 代码/CLI | 完整的WCAG检测 |
| Lighthouse | Chrome扩展 | CLI/CI | 综合性能+可访问性 |
| Pa11y | CLI工具 | CLI/CI | 基于axe-core |
| eslint-plugin-jsx-a11y | ESLint插件 | 开发时 | React特定规则 |
| Cypress-axe | Cypress插件 | E2E测试 | 集成到端到端测试 |
axe-core 使用指南
基础使用
// 安装
npm install axe-core
// 基本检测
import axe from 'axe-core';
async function runAxeTest() {
const results = await axe.run(document, {
// 配置选项
runOnly: {
type: 'tag',
values: ['wcag2a', 'wcag2aa', 'wcag21aa']
}
});
// 处理结果
if (results.violations.length > 0) {
console.error('发现可访问性问题:', results.violations);
// 输出详细信息
results.violations.forEach((violation, index) => {
console.log(`\\n问题 ${index + 1}: ${violation.help}`);
console.log(`影响: ${violation.impact}`);
console.log('元素:', violation.nodes.map(n => n.target).join(', '));
});
} else {
console.log('可访问性检测通过!');
}
return results;
}
自定义规则
const customRules = [{
id: 'custom-button-rule',
description: '自定义按钮规则',
help: '按钮必须有明确的文本内容',
helpUrl: 'https://example.com/button-accessibility',
category: 'custom',
severity: 'error',
matches: function(node, options, virtualNode) {
return node.nodeName === 'BUTTON';
},
test: function(node, options, virtualNode) {
const textContent = virtualNode.text || '';
return textContent.trim().length > 0;
}
}];
// 使用自定义规则运行检测
async function runCustomAxeTest() {
const results = await axe.run(document, {
rules: {
…axe.getDefaultRules(),
'custom-button-rule': customRules[0]
}
});
return results;
}
Lighthouse 集成
CLI使用
# 安装Lighthouse
npm install -g lighthouse
# 运行检测
lighthouse https://example.com –view
# 仅检测可访问性
lighthouse https://example.com –only-categories=accessibility
编程式使用
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');
async function runLighthouse(url) {
const chrome = await chromeLauncher.launch({ chromeFlags: ['–headless'] });
const options = {
logLevel: 'info',
output: 'json',
onlyCategories: ['accessibility'],
port: chrome.port
};
const runnerResult = await lighthouse(url, options);
const accessibilityScore = runnerResult.lhr.categories.accessibility.score * 100;
console.log(`可访问性得分: ${accessibilityScore}分`);
// 输出详细报告
runnerResult.lhr.audits.forEach(audit => {
if (audit.score === 0) {
console.log(`\\n失败: ${audit.title}`);
console.log(audit.description);
}
});
await chrome.kill();
return runnerResult;
}
runLighthouse('https://example.com');
ESLint 集成
eslint-plugin-jsx-a11y
# 安装
npm install eslint-plugin-jsx-a11y –save-dev
// .eslintrc.js
module.exports = {
plugins: ['jsx-a11y'],
rules: {
// 强制img标签有alt属性
'jsx-a11y/alt-text': 'error',
// 强制按钮有明确的文本
'jsx-a11y/button-has-type': 'error',
// 强制label与表单元素关联
'jsx-a11y/label-has-associated-control': 'error',



