04_测试与可访问性
单元、组件、端到端测试与键盘、焦点、语义和辅助技术检查。
前端测试与可访问性
学习目标:用行为测试覆盖关键用户流程,并让键盘与辅助技术用户也能完成任务。
1. 测试用户看到的行为
单元测试验证纯函数;组件测试验证表单、状态和错误反馈;端到端测试验证登录到完成操作的关键流程。Vue 可使用 Vue Test Utils,React 可使用 Testing Library;Vitest 可运行多数单元与组件测试,Playwright 适合浏览器端到端测试。
// Playwright 示例:页面已实现相应的语义化控件时可直接使用
await page.goto('/notes');
await page.getByRole('button', { name: '新增笔记' }).click();
await page.getByRole('textbox', { name: '标题' }).fill('第一条');
await page.getByRole('button', { name: '保存' }).click();
await expect(page.getByText('第一条')).toBeVisible();
以角色和可访问名称定位元素,比依赖任意 CSS 类名更接近用户行为。测试应独立准备数据,不能依赖运行顺序。
2. 可访问性检查
可访问性(accessibility)要求不同输入方式和感知能力的用户都能使用核心功能。最低检查:
- 只用键盘走通登录、搜索、创建、编辑和退出,焦点顺序合理且始终可见。
- 输入有标签,错误提示与字段关联,弹窗打开/关闭后焦点回到合理位置。
- 页面标题、地标和状态更新可被辅助技术理解;颜色不是唯一信息来源。
- 在窄屏与放大 200% 的页面上完成同样任务。
自动扫描工具可发现部分问题,但不能代替键盘与真实使用流程检查。优先使用原生 HTML 语义,再补必要 ARIA 属性。
3. 最小测试矩阵
| 场景 | 组件测试 | 端到端测试 |
|---|---|---|
| 空标题 | 显示字段错误 | 不发起有效创建 |
| 服务端 403 | 显示无权限反馈 | 用户无法编辑他人数据 |
| 网络失败 | 保留输入并允许重试 | 不出现假成功 |
| 键盘操作 | 关键按钮可触发 | 完成核心流程 |
自测
- 为什么
getByRole往往比.save-button更稳健?它依赖用户可感知的语义,而不是实现类名。 - 自动可访问性扫描能发现所有问题吗?不能,还需人工走关键流程。
4. 设计能诊断失败的测试
每个测试只承担清楚的行为:例如“空标题时显示字段错误并不调用 API”“403 时保留当前输入并显示无权限说明”。网络替身应有明确的成功、失败和延迟响应;不要用一个总是成功的 Mock 让测试失去意义。端到端测试准备独立数据,并在结束后清理,避免依赖前一个测试的结果。
await page.getByRole('textbox', { name: '标题' }).fill('');
await page.getByRole('button', { name: '保存' }).click();
await expect(page.getByText('标题不能为空')).toBeVisible();
上段是片段,需根据页面实际的验证文案和 Playwright 测试环境调整。测试失败时优先保留截图、网络日志和 trace,避免盲目加固定等待时间。
5. 手工可访问性验收
依次检查:从页面顶部只用键盘进入搜索、创建、编辑、删除;焦点可见且顺序与视觉一致;弹窗关闭后焦点回到触发按钮;错误提示与输入关联;状态更新能被辅助技术获知。然后在 200% 放大和窄屏下重复核心流程。自动扫描可辅助发现缺少标签、对比度等问题,但无法证明任务一定能完成。
练习:故意把一个 <button> 改成可点击 <div>,比较键盘触发、焦点和读屏语义;恢复原生按钮并记录少写了哪些额外代码。