← Frontend / 全栈实践

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)要求不同输入方式和感知能力的用户都能使用核心功能。最低检查:

  1. 只用键盘走通登录、搜索、创建、编辑和退出,焦点顺序合理且始终可见。
  2. 输入有标签,错误提示与字段关联,弹窗打开/关闭后焦点回到合理位置。
  3. 页面标题、地标和状态更新可被辅助技术理解;颜色不是唯一信息来源。
  4. 在窄屏与放大 200% 的页面上完成同样任务。

自动扫描工具可发现部分问题,但不能代替键盘与真实使用流程检查。优先使用原生 HTML 语义,再补必要 ARIA 属性。

3. 最小测试矩阵

场景 组件测试 端到端测试
空标题 显示字段错误 不发起有效创建
服务端 403 显示无权限反馈 用户无法编辑他人数据
网络失败 保留输入并允许重试 不出现假成功
键盘操作 关键按钮可触发 完成核心流程
易错点:快照测试通过不代表交互正确;一个按钮能显示,也不代表能用键盘触发。

自测

  1. 为什么 getByRole 往往比 .save-button 更稳健?它依赖用户可感知的语义,而不是实现类名。
  2. 自动可访问性扫描能发现所有问题吗?不能,还需人工走关键流程。

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>,比较键盘触发、焦点和读屏语义;恢复原生按钮并记录少写了哪些额外代码。