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

无障碍是一种实践,旨在让每个人都能使用应用程序。这意味着要确保你的应用程序兼容辅助技术,支持键盘导航、高对比度模式、减少动态效果等。
验证 UI 无障碍最准确的方法是在真实设备上手动测试。但手动测试需要投入大量精力,因此大多数团队使用像 Axe 这样的自动化工具作为第一道防线。
本文将展示如何使用 Storybook 运行自动化无障碍测试。你将学习如何配置 Storybook 测试运行器,使其对所有组件运行 Axe 测试,并对无障碍树进行快照。

在编码时测试无障碍性
在编码时修复无障碍问题比应用程序部署后再修复更容易。Axe 等自动化工具通过审查渲染的 DOM 来工作。这使得开发者在构建 UI 时就能发现并解决缺陷。
Axe 根据 WCAG 规则和其他行业公认的最佳实践运行检查。使用 Axe 并不能自动使你的 UI 无障碍,但平均可以发现 57% 的 WCAG 问题。
Storybook 的无障碍插件 (Accessibility addon) 会对当前选中的 story 运行 Axe 测试,并在无障碍面板中可视化测试结果。它甚至可以高亮 DOM 节点,帮助你快速找出违规之处。
在处理组件时,你可以循环浏览其 stories,以验证其外观并找出无障碍问题。

请参阅设置指南,了解有关使用和配置 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,
},
})
},
};
preRender
和 postRender
是方便的钩子函数,允许你配置测试运行器执行额外的任务。我们使用这些钩子将 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
启动测试运行器。

导出测试结果
默认情况下,结果通过 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 (@storybookjs) May 19, 2022
新教程——学习如何使用 Storybook 运行 a11y 检查。
♿ 使用 a11y 插件在编码时进行测试
🤖 使用测试运行器捕获回归问题
🌲 使用钩子函数对 a11y 树进行快照https://#/OZbnN0Az7o pic.twitter.com/Xzrbqy3Xb7