Skip to content

12.3 可访问性测试

关键词: 可访问性测试, 自动化测试工具, 手动测试方法, 用户测试, 可访问性审核, 持续改进, WCAG测试, 屏幕阅读器测试

学习目标

  • 掌握可访问性测试的基本方法和流程
  • 学会使用自动化工具进行可访问性检测
  • 了解手动测试的技巧和重点
  • 掌握用户测试的组织和实施方法
  • 学会建立持续改进的可访问性测试体系

12.3.1 自动化测试工具

浏览器扩展工具

axe DevTools

html
<!-- 测试页面示例 -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>可访问性测试页面</title>
</head>
<body>
    <header>
        <h1>网站标题</h1>
        <nav>
            <ul>
                <li><a href="#home">首页</a></li>
                <li><a href="#about">关于我们</a></li>
            </ul>
        </nav>
    </header>
    
    <main>
        <h2>主要内容</h2>
        <form>
            <input type="text" placeholder="用户名">
            <input type="password" placeholder="密码">
            <button type="submit">登录</button>
        </form>
    </main>
</body>
</html>

WAVE Web Accessibility Evaluator

javascript
// 在控制台中运行WAVE测试
// 安装WAVE扩展后,点击工具栏图标即可进行测试

// 常见的WAVE报告问题类型:
// - 错误(Errors):可访问性问题
// - 警告(Alerts):需要审查的项目
// - 特性(Features):良好的可访问性特性
// - 结构(Structural Elements):页面结构元素
// - ARIA:ARIA相关元素

Lighthouse可访问性审核

javascript
// 使用Lighthouse进行可访问性测试
// 1. 打开Chrome DevTools
// 2. 切换到Lighthouse面板
// 3. 选择"Accessibility"选项
// 4. 点击"Generate report"

// 通过命令行运行Lighthouse
// npm install -g lighthouse
// lighthouse https://example.com --only-categories=accessibility

在线测试工具

WebAIM WAVE

html
<!-- 测试表单可访问性 -->
<form>
    <!-- 问题:缺少标签 -->
    <input type="text" name="username" placeholder="用户名">
    
    <!-- 改进:添加标签 -->
    <label for="username">用户名:</label>
    <input type="text" id="username" name="username" required>
    
    <!-- 问题:颜色对比度不足 -->
    <style>
        .low-contrast {
            color: #cccccc;
            background-color: #ffffff;
        }
    </style>
    
    <!-- 改进:提高对比度 -->
    <style>
        .high-contrast {
            color: #333333;
            background-color: #ffffff;
        }
    </style>
</form>

Color Contrast Analyzer

css
/* 颜色对比度测试 */
.text-examples {
    /* 不符合WCAG标准的对比度 */
    .low-contrast {
        color: #999999;
        background-color: #ffffff;
        /* 对比度比例:2.85:1 (不符合AA标准) */
    }
    
    /* 符合WCAG AA标准的对比度 */
    .medium-contrast {
        color: #666666;
        background-color: #ffffff;
        /* 对比度比例:5.74:1 (符合AA标准) */
    }
    
    /* 符合WCAG AAA标准的对比度 */
    .high-contrast {
        color: #333333;
        background-color: #ffffff;
        /* 对比度比例:12.63:1 (符合AAA标准) */
    }
}

命令行工具

axe-core CLI

bash
# 安装axe-core CLI
npm install -g @axe-core/cli

# 测试单个页面
axe https://example.com

# 测试多个页面
axe https://example.com https://example.com/about

# 生成详细报告
axe https://example.com --reporter html --outfile accessibility-report.html

# 测试特定规则
axe https://example.com --rules color-contrast,keyboard-navigation

Pa11y测试工具

javascript
// Pa11y配置文件 (.pa11yrc)
{
    "standard": "WCAG2AA",
    "timeout": 30000,
    "wait": 500,
    "chromeLaunchConfig": {
        "executablePath": "/path/to/chrome",
        "ignoreHTTPSErrors": true
    },
    "rules": [
        "color-contrast",
        "heading-order",
        "label-title-only"
    ]
}

// 命令行使用
// npm install -g pa11y
// pa11y https://example.com
// pa11y --sitemap https://example.com/sitemap.xml

12.3.2 手动测试方法

键盘导航测试

html
<!-- 键盘导航测试页面 -->
<div class="keyboard-test">
    <h2>键盘导航测试</h2>
    
    <!-- 可聚焦元素 -->
    <a href="#link1">链接1</a>
    <button type="button">按钮1</button>
    <input type="text" placeholder="文本输入">
    <select>
        <option>选项1</option>
        <option>选项2</option>
    </select>
    <textarea placeholder="文本区域"></textarea>
    
    <!-- 自定义可聚焦元素 -->
    <div tabindex="0" role="button" class="custom-button">
        自定义按钮
    </div>
    
    <!-- Skip链接 -->
    <a href="#main-content" class="skip-link">跳转到主要内容</a>
</div>

<style>
.skip-link {
    position: absolute;
    top: -40px;
    left: 6px;
    background: #000;
    color: #fff;
    padding: 8px;
    text-decoration: none;
    z-index: 1000;
}

.skip-link:focus {
    top: 6px;
}

.custom-button {
    display: inline-block;
    padding: 8px 16px;
    background: #007cba;
    color: white;
    cursor: pointer;
    border-radius: 4px;
}

.custom-button:focus {
    outline: 2px solid #fff;
    outline-offset: 2px;
}
</style>

键盘测试检查清单

javascript
// 键盘测试检查清单
const keyboardTestChecklist = {
    // Tab键导航
    tabNavigation: {
        canNavigateToAllInteractiveElements: true,
        tabOrderIsLogical: true,
        focusIndicatorVisible: true,
        noKeyboardTraps: true
    },
    
    // 特殊键功能
    specialKeys: {
        enterActivatesButtons: true,
        spaceActivatesButtons: true,
        arrowKeysNavigateMenus: true,
        escapeClosesDialogs: true
    },
    
    // 跳转链接
    skipLinks: {
        skipLinksPresent: true,
        skipLinksWork: true,
        skipLinksVisible: true
    }
};

// 键盘测试步骤
function performKeyboardTest() {
    console.log('开始键盘测试:');
    console.log('1. 使用Tab键导航所有交互元素');
    console.log('2. 使用Shift+Tab反向导航');
    console.log('3. 使用Enter和Space激活按钮');
    console.log('4. 使用箭头键导航菜单');
    console.log('5. 使用Escape关闭对话框');
    console.log('6. 测试跳转链接功能');
}

屏幕阅读器测试

html
<!-- 屏幕阅读器测试页面 -->
<div class="screen-reader-test">
    <h1>屏幕阅读器测试页面</h1>
    
    <!-- 地标元素 -->
    <nav aria-label="主导航">
        <ul>
            <li><a href="#home">首页</a></li>
            <li><a href="#about">关于我们</a></li>
        </ul>
    </nav>
    
    <main>
        <h2>主要内容</h2>
        
        <!-- 表单测试 -->
        <form>
            <fieldset>
                <legend>个人信息</legend>
                
                <label for="name">姓名:</label>
                <input type="text" id="name" name="name" required
                       aria-describedby="name-help">
                <div id="name-help">请输入您的真实姓名</div>
                
                <label for="email">邮箱:</label>
                <input type="email" id="email" name="email" required
                       aria-describedby="email-help">
                <div id="email-help">用于接收通知邮件</div>
            </fieldset>
            
            <button type="submit">提交</button>
        </form>
        
        <!-- 动态内容测试 -->
        <div id="status" aria-live="polite" aria-atomic="true">
            <!-- 状态消息 -->
        </div>
        
        <div id="alerts" aria-live="assertive" aria-atomic="true">
            <!-- 重要警告 -->
        </div>
    </main>
    
    <aside>
        <h3>相关链接</h3>
        <ul>
            <li><a href="#related1">相关文章1</a></li>
            <li><a href="#related2">相关文章2</a></li>
        </ul>
    </aside>
</div>

颜色和对比度测试

html
<!-- 颜色对比度测试 -->
<div class="color-contrast-test">
    <h2>颜色对比度测试</h2>
    
    <!-- 文本颜色测试 -->
    <div class="text-samples">
        <p style="color: #000000; background: #ffffff;">
            黑色文本 - 白色背景 (21:1)
        </p>
        <p style="color: #333333; background: #ffffff;">
            深灰色文本 - 白色背景 (12.63:1)
        </p>
        <p style="color: #666666; background: #ffffff;">
            灰色文本 - 白色背景 (5.74:1)
        </p>
        <p style="color: #999999; background: #ffffff;">
            浅灰色文本 - 白色背景 (2.85:1) - 不符合标准
        </p>
    </div>
    
    <!-- 链接颜色测试 -->
    <div class="link-samples">
        <p>
            这是一段包含
            <a href="#" style="color: #0073aa;">标准链接</a>
            的文本。
        </p>
        <p>
            这是一段包含
            <a href="#" style="color: #cccccc;">低对比度链接</a>
            的文本 - 不符合标准。
        </p>
    </div>
    
    <!-- 按钮颜色测试 -->
    <div class="button-samples">
        <button style="background: #007cba; color: #ffffff;">
            高对比度按钮
        </button>
        <button style="background: #cccccc; color: #ffffff;">
            低对比度按钮 - 不符合标准
        </button>
    </div>
</div>

12.3.3 用户测试

残障用户测试

html
<!-- 用户测试准备页面 -->
<div class="user-test-page">
    <h1>用户测试页面</h1>
    
    <!-- 任务导向的测试内容 -->
    <nav aria-label="主导航">
        <ul>
            <li><a href="#task1">任务1:注册账户</a></li>
            <li><a href="#task2">任务2:搜索产品</a></li>
            <li><a href="#task3">任务3:完成购买</a></li>
        </ul>
    </nav>
    
    <main>
        <section id="task1">
            <h2>任务1:用户注册</h2>
            <form>
                <fieldset>
                    <legend>注册信息</legend>
                    
                    <label for="reg-username">用户名:</label>
                    <input type="text" id="reg-username" name="username" required
                           aria-describedby="username-help">
                    <div id="username-help">
                        用户名长度为3-20个字符,只能包含字母、数字和下划线
                    </div>
                    
                    <label for="reg-email">邮箱地址:</label>
                    <input type="email" id="reg-email" name="email" required>
                    
                    <label for="reg-password">密码:</label>
                    <input type="password" id="reg-password" name="password" required
                           aria-describedby="password-help">
                    <div id="password-help">
                        密码至少8个字符,包含字母和数字
                    </div>
                    
                    <button type="submit">注册</button>
                </fieldset>
            </form>
        </section>
        
        <section id="task2">
            <h2>任务2:产品搜索</h2>
            <form role="search">
                <label for="search-input">搜索产品:</label>
                <input type="search" id="search-input" name="search"
                       aria-describedby="search-help">
                <div id="search-help">
                    输入产品名称或关键词进行搜索
                </div>
                <button type="submit">搜索</button>
            </form>
            
            <div id="search-results" aria-live="polite">
                <!-- 搜索结果将显示在这里 -->
            </div>
        </section>
    </main>
</div>

用户测试计划

javascript
// 用户测试计划
const userTestPlan = {
    // 测试目标
    objectives: [
        '评估网站的整体可访问性',
        '识别用户在完成核心任务时的困难',
        '验证辅助技术的兼容性',
        '收集用户体验反馈'
    ],
    
    // 参与者要求
    participants: {
        screenReaderUsers: {
            count: 5,
            experience: ['初级', '中级', '高级'],
            assistiveTech: ['NVDA', 'JAWS', 'VoiceOver']
        },
        keyboardUsers: {
            count: 3,
            disabilities: ['运动障碍', '视力障碍']
        },
        cognitiveUsers: {
            count: 3,
            disabilities: ['学习障碍', '认知障碍']
        }
    },
    
    // 测试任务
    tasks: [
        {
            name: '账户注册',
            description: '完成用户注册流程',
            successCriteria: '能够成功创建账户',
            timeLimit: 10
        },
        {
            name: '信息搜索',
            description: '搜索特定产品信息',
            successCriteria: '找到所需产品',
            timeLimit: 5
        },
        {
            name: '表单提交',
            description: '填写并提交联系表单',
            successCriteria: '成功提交表单',
            timeLimit: 8
        }
    ],
    
    // 数据收集
    dataCollection: {
        quantitative: ['任务完成率', '任务完成时间', '错误次数'],
        qualitative: ['用户满意度', '困难点', '改进建议']
    }
};

测试后的用户反馈收集

html
<!-- 用户反馈表单 -->
<div class="feedback-form">
    <h2>用户测试反馈表</h2>
    
    <form>
        <fieldset>
            <legend>基本信息</legend>
            
            <label for="user-type">您使用的辅助技术:</label>
            <select id="user-type" name="assistive-tech">
                <option value="">请选择</option>
                <option value="screen-reader">屏幕阅读器</option>
                <option value="keyboard-only">仅键盘导航</option>
                <option value="voice-control">语音控制</option>
                <option value="magnification">屏幕放大</option>
                <option value="other">其他</option>
            </select>
        </fieldset>
        
        <fieldset>
            <legend>任务体验评价</legend>
            
            <label for="task-difficulty">整体任务难度:</label>
            <select id="task-difficulty" name="difficulty">
                <option value="very-easy">非常容易</option>
                <option value="easy">容易</option>
                <option value="moderate">中等</option>
                <option value="difficult">困难</option>
                <option value="very-difficult">非常困难</option>
            </select>
            
            <label for="satisfaction">整体满意度:</label>
            <div role="radiogroup" aria-labelledby="satisfaction">
                <label>
                    <input type="radio" name="satisfaction" value="5">
                    非常满意
                </label>
                <label>
                    <input type="radio" name="satisfaction" value="4">
                    满意
                </label>
                <label>
                    <input type="radio" name="satisfaction" value="3">
                    一般
                </label>
                <label>
                    <input type="radio" name="satisfaction" value="2">
                    不满意
                </label>
                <label>
                    <input type="radio" name="satisfaction" value="1">
                    非常不满意
                </label>
            </div>
        </fieldset>
        
        <fieldset>
            <legend>详细反馈</legend>
            
            <label for="difficulties">遇到的困难:</label>
            <textarea id="difficulties" name="difficulties" rows="4"
                      placeholder="请描述您在使用过程中遇到的困难"></textarea>
            
            <label for="suggestions">改进建议:</label>
            <textarea id="suggestions" name="suggestions" rows="4"
                      placeholder="请提供您的改进建议"></textarea>
        </fieldset>
        
        <button type="submit">提交反馈</button>
    </form>
</div>

12.3.4 可访问性审核

审核检查清单

javascript
// 可访问性审核检查清单
const accessibilityAuditChecklist = {
    // 感知能力 (Perceivable)
    perceivable: {
        textAlternatives: {
            imagesHaveAltText: false,
            decorativeImagesMarked: false,
            complexImagesDescribed: false
        },
        timeBasedMedia: {
            videosHaveCaptions: false,
            audioHasTranscripts: false,
            audioDescriptionProvided: false
        },
        adaptable: {
            contentStructureLogical: false,
            meaningNotLostInPresentation: false,
            headingStructureCorrect: false
        },
        distinguishable: {
            colorNotOnlyMeansOfConveyingInfo: false,
            contrastRatioMeetsStandards: false,
            textCanBeResized: false,
            imagesOfTextAvoided: false
        }
    },
    
    // 可操作性 (Operable)
    operable: {
        keyboardAccessible: {
            allContentKeyboardAccessible: false,
            noKeyboardTraps: false,
            keyboardShortcutsDocumented: false
        },
        seizures: {
            nothingFlashesMoreThanThreeTimes: false
        },
        navigable: {
            skipLinksProvided: false,
            pageHasTitle: false,
            linkPurposeClear: false,
            focusVisible: false,
            focusOrderLogical: false
        },
        inputModalities: {
            motionActivationAlternatives: false,
            clickTargetSizeAdequate: false
        }
    },
    
    // 可理解性 (Understandable)
    understandable: {
        readable: {
            pageLanguageDefined: false,
            languageChangesIndicated: false,
            readingLevelAppropriate: false
        },
        predictable: {
            onFocusNoContextChange: false,
            onInputNoContextChange: false,
            navigationConsistent: false,
            identificationConsistent: false
        },
        inputAssistance: {
            errorsIdentifiedAndDescribed: false,
            labelsAndInstructionsProvided: false,
            errorSuggestionProvided: false,
            errorPreventionForImportantData: false
        }
    },
    
    // 健壮性 (Robust)
    robust: {
        compatible: {
            validHtmlUsed: false,
            nameRoleValueForUIComponents: false,
            assistiveTechCompatible: false
        }
    }
};

审核报告模板

html
<!-- 可访问性审核报告模板 -->
<div class="audit-report">
    <h1>可访问性审核报告</h1>
    
    <section class="executive-summary">
        <h2>执行摘要</h2>
        <p>本次审核评估了网站的可访问性合规性,基于WCAG 2.1 AA标准。</p>
        
        <div class="key-findings">
            <h3>主要发现</h3>
            <ul>
                <li>发现42个可访问性问题</li>
                <li>其中15个为严重问题</li>
                <li>整体合规率为68%</li>
            </ul>
        </div>
        
        <div class="recommendations">
            <h3>主要建议</h3>
            <ul>
                <li>为所有图像添加适当的替代文本</li>
                <li>改进表单标签和验证</li>
                <li>提高颜色对比度</li>
                <li>修复键盘导航问题</li>
            </ul>
        </div>
    </section>
    
    <section class="detailed-findings">
        <h2>详细发现</h2>
        
        <div class="issue-category">
            <h3>严重问题 (15个)</h3>
            
            <div class="issue">
                <h4>图像缺少替代文本</h4>
                <p><strong>影响:</strong>屏幕阅读器用户无法理解图像内容</p>
                <p><strong>位置:</strong>首页轮播图, 产品列表页</p>
                <p><strong>WCAG准则:</strong>1.1.1 非文本内容</p>
                <p><strong>建议:</strong>为所有信息性图像添加描述性的alt属性</p>
            </div>
            
            <div class="issue">
                <h4>表单控件缺少标签</h4>
                <p><strong>影响:</strong>用户无法理解表单字段的用途</p>
                <p><strong>位置:</strong>联系表单, 注册页面</p>
                <p><strong>WCAG准则:</strong>1.3.1 信息和关系</p>
                <p><strong>建议:</strong>为所有表单控件添加相关联的标签</p>
            </div>
        </div>
        
        <div class="issue-category">
            <h3>中等问题 (18个)</h3>
            <!-- 中等问题列表 -->
        </div>
        
        <div class="issue-category">
            <h3>轻微问题 (9个)</h3>
            <!-- 轻微问题列表 -->
        </div>
    </section>
</div>

12.3.5 持续改进

可访问性测试流程

javascript
// 可访问性测试流程
const accessibilityTestingWorkflow = {
    // 开发阶段
    development: {
        codeReview: {
            checkSemanticHtml: true,
            validateAriaUsage: true,
            reviewColorContrast: true,
            testKeyboardNavigation: true
        },
        automatedTesting: {
            runAxeCoreTests: true,
            checkLintRules: true,
            validateHtml: true
        }
    },
    
    // 测试阶段
    testing: {
        automatedTests: {
            runAxeDevTools: true,
            runLighthouseAudit: true,
            runPa11yTests: true
        },
        manualTests: {
            keyboardTesting: true,
            screenReaderTesting: true,
            colorBlindnessTesting: true
        }
    },
    
    // 发布前
    preRelease: {
        comprehensiveAudit: true,
        userTesting: true,
        expertReview: true
    },
    
    // 发布后
    postRelease: {
        continuousMonitoring: true,
        userFeedbackCollection: true,
        regularAudits: true
    }
};

可访问性指标追踪

html
<!-- 可访问性指标仪表板 -->
<div class="accessibility-dashboard">
    <h2>可访问性指标仪表板</h2>
    
    <div class="metrics-grid">
        <div class="metric-card">
            <h3>合规率</h3>
            <div class="metric-value">85%</div>
            <div class="metric-trend">↑ 5%</div>
        </div>
        
        <div class="metric-card">
            <h3>严重问题</h3>
            <div class="metric-value">3</div>
            <div class="metric-trend">↓ 2</div>
        </div>
        
        <div class="metric-card">
            <h3>用户满意度</h3>
            <div class="metric-value">4.2/5</div>
            <div class="metric-trend">↑ 0.3</div>
        </div>
        
        <div class="metric-card">
            <h3>任务完成率</h3>
            <div class="metric-value">92%</div>
            <div class="metric-trend">↑ 8%</div>
        </div>
    </div>
    
    <div class="charts">
        <div class="chart-container">
            <h3>问题趋势图</h3>
            <!-- 图表将在这里显示 -->
        </div>
        
        <div class="chart-container">
            <h3>页面合规率</h3>
            <!-- 图表将在这里显示 -->
        </div>
    </div>
</div>

团队培训和流程

javascript
// 可访问性培训计划
const accessibilityTrainingPlan = {
    // 基础培训
    basicTraining: {
        duration: '2天',
        topics: [
            '可访问性基础概念',
            'WCAG指南介绍',
            '辅助技术体验',
            '基本测试方法'
        ],
        audience: '所有开发人员'
    },
    
    // 进阶培训
    advancedTraining: {
        duration: '3天',
        topics: [
            '复杂组件可访问性',
            'ARIA高级应用',
            '自动化测试设置',
            '用户测试组织'
        ],
        audience: '前端开发人员、测试人员'
    },
    
    // 定期更新
    continuousLearning: {
        frequency: '每月',
        format: '技术分享会',
        topics: [
            '最新标准更新',
            '案例分析',
            '工具介绍',
            '问题解决方案'
        ]
    }
};

// 流程集成
const processIntegration = {
    designPhase: {
        accessibilityReview: true,
        colorContrastCheck: true,
        userJourneyMapping: true
    },
    
    developmentPhase: {
        codeReview: true,
        automatedTesting: true,
        peerTesting: true
    },
    
    testingPhase: {
        manualTesting: true,
        assistiveTechTesting: true,
        userTesting: true
    },
    
    releasePhase: {
        finalAudit: true,
        documentationUpdate: true,
        trainingMaterial: true
    }
};

本节要点回顾

  • 自动化测试工具:使用axe、WAVE、Lighthouse等工具进行初步检测
  • 手动测试方法:进行键盘导航、屏幕阅读器和颜色对比度测试
  • 用户测试:组织真实用户参与测试,收集实际使用反馈
  • 可访问性审核:系统性地检查WCAG合规性并生成详细报告
  • 持续改进:建立完整的测试流程和指标追踪系统

相关学习资源

常见问题FAQ

Q: 自动化测试工具能发现所有可访问性问题吗?

A: 不能。自动化工具只能检测到约30-40%的可访问性问题,还需要结合手动测试和用户测试。

Q: 如何选择合适的屏幕阅读器进行测试?

A: 建议测试多种屏幕阅读器,包括免费的NVDA、商业的JAWS,以及移动平台的VoiceOver和TalkBack。

Q: 用户测试需要多少参与者?

A: 通常每种用户类型需要3-5名参与者。对于屏幕阅读器用户,建议至少5名不同技能水平的用户。

Q: 如何平衡开发速度和可访问性测试?

A: 将可访问性测试集成到现有的开发流程中,使用自动化工具提高效率,并建立可访问性检查清单。

Q: 如何说服团队投资可访问性测试?

A: 强调法律风险、市场机会、品牌价值,并提供具体的ROI数据和用户案例。


下一节预览:下一节我们将学习HTML5安全性,重点介绍Web安全威胁、HTML5安全特性和安全最佳实践。