返回博客

使用 Storybook 自动化可访问性测试

使用无障碍插件在开发过程中运行检查,并使用测试运行器捕获回归问题

loading
Varun Vachhar
@winkerVSbecks
上次更新时间

无障碍是一种实践,旨在让每个人都能使用应用程序。这意味着要确保你的应用程序兼容辅助技术,支持键盘导航、高对比度模式、减少动态效果等。

验证 UI 无障碍最准确的方法是在真实设备上手动测试。但手动测试需要投入大量精力,因此大多数团队使用像 Axe 这样的自动化工具作为第一道防线。

本文将展示如何使用 Storybook 运行自动化无障碍测试。你将学习如何配置 Storybook 测试运行器,使其对所有组件运行 Axe 测试,并对无障碍树进行快照。

在编码时测试无障碍性

在编码时修复无障碍问题比应用程序部署后再修复更容易。Axe 等自动化工具通过审查渲染的 DOM 来工作。这使得开发者在构建 UI 时就能发现并解决缺陷。

Axe 根据 WCAG 规则和其他行业公认的最佳实践运行检查。使用 Axe 并不能自动使你的 UI 无障碍,但平均可以发现 57% 的 WCAG 问题。

Storybook 的无障碍插件 (Accessibility addon) 会对当前选中的 story 运行 Axe 测试,并在无障碍面板中可视化测试结果。它甚至可以高亮 DOM 节点,帮助你快速找出违规之处。

在处理组件时,你可以循环浏览其 stories,以验证其外观并找出无障碍问题。

Storybook highlights the offending DOM nodes and gives you an audit report

请参阅设置指南,了解有关使用和配置 A11y 插件的更多信息。

自动捕获无障碍回归问题

对组件的更改可能会无意中引入新的无障碍问题。为了捕获这些回归问题,你应该在发起拉取请求之前测试所有 stories。

无障碍插件只在你查看 story 时运行检查。我们希望通过 Storybook 测试运行器一次性运行 Axe 测试所有 stories。它是一个独立的工具(由 Jest 和 Playwright 提供支持),用于检查 stories 中的渲染错误。

接下来,我们来设置测试运行器并配置它来运行 Axe。我们将从安装测试运行器和相关软件包开始(注意,它需要 Storybook 6.4 或更高版本)。

npm i -D jest @storybook/test-runner axe-playwright

并安装 playwright 依赖项

npx playwright install --with-deps

然后,你可以使用 Storybook 测试运行器和 axe-playwright 将这些无障碍测试集成到你的测试自动化流水线中。

在 Storybook 目录中添加一个新配置文件,内容如下

// .storybook/test-runner.js
 
const { injectAxe, checkA11y } = require('axe-playwright');
 
module.exports = {
 async preRender(page, context) {
   await injectAxe(page);
 },
 async postRender(page, context) {
   await checkA11y(page, '#root', {
     detailedReport: true,
     detailedReportOptions: {
       html: true,
     },
   })
 },
};

preRenderpostRender 是方便的钩子函数,允许你配置测试运行器执行额外的任务。我们使用这些钩子将 Axe 注入到 story 中,然后在它渲染后运行无障碍测试。

你会注意到传入 checkA11y 函数的一些选项。我们已配置 Axe 从 story 的根元素开始,然后遍历 DOM 树检查问题。它还将根据遇到的问题生成详细报告,并输出违反无障碍规则的 HTML 元素列表。

要运行测试,请在 package.json 中为测试运行器添加一个脚本。

{
  "scripts": {
    "test-storybook:ci": "yarn test-storybook --maxWorkers=2"
  }
}

然后在一个终端窗口中用 npm run storybook 启动你的 Storybook,在另一个终端窗口中用 npm run test-storybook 启动测试运行器。

test runner runs accessibility checks along with all your other component tests

导出测试结果

默认情况下,结果通过 CLI 报告。要导出结果,可以切换到 getViolations 函数并使用 Node 的 fs API 将它们保存到 JSON 文件中。

// .storybook/test-runner.js
 
const { injectAxe, getViolations } = require('axe-playwright');
const fs = require('fs');
 
module.exports = {
 setup() {
   fs.mkdir(
     process.cwd() + '/src/__accessibility__/',
     { recursive: true },
     (err) => {
       if (err) throw err;
     }
   );
 },
 async preRender(page, context) {
   await injectAxe(page);
 },
 async postRender(page, context) {
   const violations = await getViolations(page, '#root', {
     detailedReport: true,
   });
 
   // Do something with violations
   // For example, write them to a file
   await new Promise((resolve, reject) => {
     fs.writeFile(
       process.cwd() + `/src/__accessibility__/${context.id}.json`,
       JSON.stringify(violations, null, 2),
       (err) => {
         if (err) reject(err);
         resolve();
       }
     );
   });
 },
};

对无障碍树进行快照以检查页面结构

盲人和视障用户依赖屏幕阅读器等辅助技术来理解你的 UI 并与之交互。浏览器会将你的标记转换为一种称为无障碍树的内部表示。这是屏幕阅读器解析 UI 并将可视化界面转换为语音的机制。

对无障碍树进行快照有助于你了解 UI 如何被这些辅助设备解析。你可以检查页面结构是否正确以及内容是否按正确顺序呈现。此外,跟踪和比较这些快照可以捕获在修改或更新 UI 时引入的回归问题。

// .storybook/test-runner.js

const { injectAxe, checkA11y } = require('axe-playwright');
 
module.exports = {
 async preRender(page, context) {
   await injectAxe(page);
 },
 async postRender(page, context) {
   await checkA11y(page, '#root', {
     detailedReport: true,
     detailedReportOptions: {
       html: true,
     },
   });
 
   const accessibilityTree = await page.accessibility.snapshot();
   expect(accessibilityTree).toMatchSnapshot();
 },
};

结论

在美国,26% 的成年人至少有一种残疾。改善无障碍性可以对你的用户群产生重大影响。

自动化无障碍测试是 QA 的第一道防线,用于捕获明显的无障碍违规行为。虽然自动化并不能自动使你的 UI 无障碍,但它可以通过让你在开发过程中发现问题来缩短反馈周期。

Storybook 无障碍插件会审计你的 stories 并高亮显示有问题的 DOM 节点。当你准备好合并时,使用 Storybook 测试运行器对所有组件运行检查以捕获回归问题。

通过我们的入门指南了解如何在 CI 中使用测试运行器。

加入 Storybook 邮件列表

获取最新新闻、更新和发布信息

7,180位开发者及以上

我们正在招聘!

加入 Storybook 和 Chromatic 背后的团队。构建被数十万开发者用于生产环境的工具。优先远程工作。

查看职位

热门文章

Storybook 6.5

提升效率的新工作流程
loading
Michael Shilman

为什么大多数设计系统会内爆

我们问了 Brad Frost:设计系统在 2022 年是否仍然重要?
loading
Michael Chan

Storybook 性能:Vite vs Webpack

我们对这两种构建工具进行了基准测试,看看哪个更快。
loading
Ian VanSchooten
加入社区
7,180位开发者及以上
为何缘何选择 Storybook组件驱动的 UI
文档指南教程更新日志遥测
社区插件参与其中博客
展示探索项目组件词汇表
开源软件
Storybook - Storybook 中文

特别感谢 Netlify CircleCI