New
Code coverage with Storybook test runnerAutomate with Chromatic
Star74,802
Back to Design Systems for Developers
React
Chapters
  • 简介
  • 架构
  • 创建
  • 审查
  • 测试
  • 文档
  • 发布
  • 工作流程
  • 总结

通过测试来保证质量

如何测试设计系统的界面、功能和无障碍访问
此社区翻译尚未更新为最新的Storybook版本。通过应用此翻译的中文指南中的更改来帮助我们更新它。 Pull requests 欢迎他们.

在第五章,我们将通过自动化脚本来测试设计系统以规避 UI 问题。本章将会深入讨论 UI 组件有哪些属性值得去测试以及如何避免潜在的问题。我们通过研究 Wave、BCC 和 Salesforce 这样的专业团队去寻求在高覆盖范围、低设置难度和低维护成本间之间找到一个平衡点。

UI 组件的测试基础

在开始之前,我们需要先搞清楚什么样的测试是合理的。设计系统是由 UI 组件组成的,每个 UI 组件都有自己的 stories, 这些 stories 描述了在不同输入值的情况下组件预期的外观是什么样子。然后 Stories 通过浏览器或者其他设备呈现给终端用户。

Component states are combinatorial

哇!如您所见,一个组件包含很多的状态。将每个组件的状态乘以在设计系统中组件的数量您就会发现持续关注每个组件是一项不可能完成的任务。实际上,手工审查每个元素的每一个状态不是长久之道,尤其当设计系统越来越庞大。

现在我们更需要设置自动测试来节约以后的工作时间。

测前须知

之前的文章 我对 4 个涉及到专业的 Storybook 工作流程的前端团队做过调查。他们认为开发 stories 是一个最佳实践,它让测试变得容易和全面。

清楚地将组件支持的状态表达为 stories 可以阐明不同的输入组合所对应的组件状态,尽可能去忽略不支持的状态来降低干扰。

使用一致性的渲染原则来避免由随机(Math.random)或相对输入(Date.now)而带来的不确定性。

“最好的 stories 应让您可视化您可以体验到的所有的组件状态” – Tim Hingston, Tech lead at Apollo GraphQL

用视觉测试来测试组件外观

设计系统包含了可展示的 UI 组件,这些组件基本上都是可视的。视觉测试验证了渲染后的 UI 组件的视觉效果。

视觉测试会在一个保持一致的浏览器环境下对每个 UI 组件截图。新的截图将会自动与之前的基准截图进行对比,如果在视觉上有任何不同,您将会被告知。

Visual test components

如果您在创建现代化 UI,视觉测试可帮助您的前端开发团队节省人工审查的时间,也可以避免昂贵的 UI 回归测试。我们将使用 Storybook 维护者提供的工业级服务 Chromatic 来演示视觉测试。

之前的章节 我们学习到如何使用 Chromatic 去发布一个 Storybook。 我们为 Button 组件添加了一个红色边框并向同事来寻求反馈。

Button red border

现在我们使用 Chromatic 内置的工具 testing tools 来看看视觉测试是如何工作的。当合并请求被创建的时候,Chromatic 获取到我们组件和之前组件的变化差异图。有 3 个改动被发现:

List of checks in the pull request

点击 "🟡 UI Tests" 按钮来浏览它们。

Second build in Chromatic with changes

您看!细微的调整导致大量的 UI 发生变化

审查这些变化来确定是有意(改进)或无意(bugs)而为之的。如果您同意该改动,那么对比基线则会更新为当前最新版本,这意味着之后的版本将会拿该基线来对比和识别 bug。

Reviewing changes in Chromatic

在上一章中,因为一些原因,我们的同事不喜欢红色边框的 Button 组件,所以我们需要拒绝修改来表明本次提交需要被撤销。

Review deny in Chromatic

撤销这些改动并且重新提交代码来发起另一轮视觉审查。

用单元测试来测试功能

单元测试验证了在给定输入下 UI 代码是否能返回正确的输出值。它与组件并存来帮助您验证特定的功能。

在像 React、Vue 和 Angular 这样的视图层中任何东西都可以看作一个组件。组件封装了各种功能,从简单的按钮到精致的日期选择器。越错综复杂的组件,越是难以用视觉测试去捕获细微的差别,这就是为什么我们需要单元测试的原因。

Unit test components

例如当与生成系统链接的组件(ReactRouter 中的 “LinkWrappers”、 Gatsby 或 Next.js)结合时,我们的 Link 组件就会变得很复杂。一个错误的实现可能就会导致我们链接没有有效的 href 值。

从视觉层面上来看,我们是无法判断 href 属性是不是指向一个正确的地方,此时使用单元测试刚好可以避免该问题。

用单元测试验证 hrefs

让我们为 Link 组件添加一个单元测试。 create-react-app 已经配置好了一个单元测试的运行环境,所以我们只需要创建一个文件 src/Link.test.js

Copy
src/Link.test.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Link } from './Link';

// A straightforward link wrapper that renders an <a> with the passed props. What we are testing
// here is that the Link component passes the right props to the wrapper and itselfs
const LinkWrapper = (props) => <a {...props} />; // eslint-disable-line jsx-a11y/anchor-has-content

it('has a href attribute when rendering with linkWrapper', () => {
  const div = document.createElement('div');
  ReactDOM.render(
    <Link href="https://learnstorybook.com" LinkWrapper={LinkWrapper}>
      Link Text
    </Link>,
    div
  );

  expect(div.querySelector('a[href="https://learnstorybook.com"]')).not.toBeNull();
  expect(div.textContent).toEqual('Link Text');

  ReactDOM.unmountComponentAtNode(div);
});

我们可以通过执行 yarn test 来运行上述测试

Running a single Jest test

之前我们已经配置了我们的 GitHub action 来部署 Storybook。现在我们可以修改它来让它帮助我们运行测试。代码贡献者也会从中获益,我们也会对强大的 Link 组件保持信心。

Copy
.github/workflows/chromatic.yml
# ... same as before
jobs:
  test:
    # the operating system it will run on
    runs-on: ubuntu-latest
    # the list of steps that the action will go through
    steps:
      - uses: actions/checkout@v1
      - run: yarn
      - run: yarn test # adds the test command
      - uses: chromaui/action@v1
        # options required to the GitHub chromatic action
        with:
          # our project token, to see how to obtain it
          # refer to https://www.learnstorybook.com/intro-to-storybook/react/en/deploy/ (update link)
          projectToken: project-token
          token: ${{ secrets.GITHUB_TOKEN }}

Successful circle build

请注意: 过多的单元测试可能会导致更新组件变得更复杂,所以建议您在设计系统中适度的使用单元测试。

"越来越强大的自动化测试套件使我们团队更有信心的加快开发脚步" – Dan Green-Leipciger, Senior software engineer at Wave

无障碍访问测试

“无障碍访问意味着所有的人(包括残疾人)都可以理解、导航并与您的应用进行交互......在线[示例包括]访问内容的其他替代方案,例如使用 Tab 键和屏幕阅读器来遍历整个网站内容”。作者:Alex Wilson from T.Rowe Price.

根据世界卫生组织统计,目前全球有 15%的残疾人。由于囊括了用户界面的 UI,所以设计系统对无障碍访问的影响很大。提高哪怕单个组件的可访问性就意味着整个公司的每个用到该实例的地方都会收益。

Storybook accessibility addon

为相关的 UI 组件添加 Storybook 的无障碍访问插件,它是一个实时验证 Web 可访问性标准(WCAG)的工具

Copy
yarn add --dev @storybook/addon-a11y

在文件 .storybook/main.js 中添加插件:

Copy
.storybook/main.js
module.exports = {
  stories: ['../src/**/*.stories.js'],
  addons: [
    '@storybook/preset-create-react-app',
    '@storybook/addon-actions',
    '@storybook/addon-links',
    '@storybook/addon-storysource',
    '@storybook/addon-knobs',
    '@storybook/addon-a11y',
  ],
};

并且在文件 .storybook/preview.js 添加 withA11y 修饰器

Copy
.storybook/preview.js
import React from 'react';
import { addDecorator } from '@storybook/react';
import { withA11y } from '@storybook/addon-a11y';

import { GlobalStyle } from '../src/components/shared/global';

addDecorator(withA11y);
addDecorator((story) => (
  <>
    <GlobalStyle />
    {story()}
  </>
));

当您完成安装后, “Accessibility” 页签将会出现在 Storybook 的插件面板中。

Storybook a11y addon

它会告诉您 DOM 元素的无障碍访问等级(违反标准或通过标准)。单击 “highlight results” 选择框便会可视化您 UI 组件不符合标准的设置。

Storybook a11y addon with passes highlighted

然后我们只需遵循插件给出的关于无障碍访问的建议即可。

其他测试策略

矛盾的是,测试可以节省时间但也会降低维护速度。您需要自己判断做正确的“测试”,而不是“全部”测试。即使软件开发有很多测试策略,我们还是发现有一些不适合设计系统的。

快照测试 (Jest)

这个技术会捕捉 UI 组件实际的输出代码,并将其与以前的版本进行比较。它并不会测试 UI 组件在浏览器中的具体表现,而是通过对比 UI 组件生成的标记代码来测试代码实现细节是否发生变化。

利用快照来对比代码差异是不可预测的,容易产生误报。在组件级别,代码快照是无法兼顾到设计变量、css 和 第三方 API 更新(网络字体, stripe 表单,Google Maps 等)等全局上的更改。实际上,开发人员往往会重新生成快照或直接忽略快照测试。

大多数情况下的组件快照测试只是低配版的截图测试。测试您的输出,应更加关注在内容上面而不是底层的标记代码(很容易改变!)。 – Mark Dalgliesh, Frontend infrastructure at SEEK, CSS modules creator

端到端测试 (Selenium, Cypress)

端到端测试用来模拟用户的操作,它们比较适合应用在应用程序的一个流程上(比如:注册或者结账流程),功能越复杂该测试策略越有效。

设计系统大多由功能相对简单的原子组件构成,往往不需要验证用户流程,而且创建测试其实是比较耗时的,也需要经常维护。但是,在极少数情况下,端到端测试可能会帮助到组件,例如,验证复杂的 UI 组件(如:日期选择器或付款表单)。

使用文档推动组件的使用

由于设计系统为整个组织的干系人服务,所以不仅仅只有测试,我们需要教别人如果使用经过良好测试的 UI 组件。

在第六章,我们将学习如何通过文档来推动组件的使用,深入了解为什么说用较少的工作就能创建比较全面的文档的 Storybook Docs 插件是一个秘密武器。

Keep your code in sync with this chapter. View a676146 on GitHub.
Is this free guide helping you? Tweet to give kudos and help other devs find it.
Next Chapter
文档
通过文档推动设计系统的使用
✍️ Edit on GitHub – PRs welcome!
Join the community
5,870 developers and counting
WhyWhy StorybookComponent-driven UI
Open source software
Storybook

Maintained by
Chromatic
Special thanks to Netlify and CircleCI