返回博客

UI 测试实用指南

不会拖慢您速度的测试工作流程

loading
Varun Vachhar
@winkerVSbecks
最后更新

UI 测试工作流常常会陷入维护的噩梦。只要稍作实现上的调整,您的测试就会中断。您需要为每个工具重复创建测试用例。

不难找到测试 UI 不同部分的工具。但如何将它们组合成一个高效的工作流却颇具挑战。如果处理不当,UI 开发流程就会变得步履维艰。

我采访了来自 Twilio、Adobe、Peloton 和 Shopify 等公司的十个团队,了解他们如何平衡 UI 测试的投入和价值。尽管团队规模和技术栈各不相同,但大家都有相似的策略。本文将这些经验汇集,形成了如下实用的工作流。

  1. 📚 使用 Storybook 隔离组件。 编写测试用例,通过 props 和 mock 数据重现每种状态。
  2. 使用 Chromatic 捕获视觉 bug 并验证组合。
  3. 🐙 使用 JestTesting Library 验证交互。
  4. ♿️ 使用 Axe 审计组件的可访问性。
  5. 🔄 使用 Cypress 编写端到端测试,验证用户流程。
  6. 🚥 使用 GitHub Actions 自动运行测试,捕获回归。

行之有效的方法

构建和测试 UI 组件应该是无缝的。这取决于两个方面:减轻维护负担,同时增加运行测试的灵活性。

在组件层面进行测试,更快地发现 bug

我调查的团队也表示,他们大多在组件层面运行测试。组件允许您将界面分解成隔离的单元。隔离测试更容易定位 bug。

重用 Story,减少维护

每种类型的测试都使用不同的工具。这意味着您经常需要一遍又一遍地复制相同的组件状态。这很难设置和维护。Storybook 允许您隔离组件,并将所有测试用例捕获在 *.stories.js 文件中。然后,您可以将它们导入到 Jest 和 Cypress 等工具中。最终,您只需编写一次测试用例。

编码时进行测试,以加快反馈循环

在开发过程中,您专注于与您正在开发的功能相关的少数几个组件。因此,您只想对这些组件运行有针对性的测试。

在合并之前运行所有检查

当您准备合并时,您需要检查回归 bug。这意味着需要使用 CI 服务器自动运行整个测试套件。

UI 测试工作流教程

为了演示这个过程,我将使用Taskbox 应用——一个类似于 Asana 的任务管理应用。之前,我们已经探讨了如何为这个 UI 编写所有不同类型的测试。现在,让我们添加删除任务的功能,并逐步完成整个测试工作流。

为了本次演示,我们直接进入准备测试的阶段。如果您对实现细节感兴趣,可以查看项目仓库

视觉和组合测试

首先,我们只想更新 UI 并确保所有样式都符合规范。我们将向 Task 组件添加删除按钮。

开发过程中

您可以使用 Storybook 来关注 Task 组件,而不是启动整个应用程序。然后,循环浏览其所有 Stories,手动验证其外观。

PR 检查

对 Task UI 的修改可能会导致其在其他组件(TaskList 和 InboxScreen)中的意外更改。使用 Chromatic 运行视觉测试将能发现这些问题。它还将确保所有内容都已正确连接。

创建 pull request 时,Chromatic 会自动触发。完成后,您将看到一个 diff 供您审查。在这种情况下,更改是故意的。按“接受”按钮即可更新基线。

可访问性测试

开发过程中

在开发过程中,在 Storybook 中运行可访问性检查。A11y 插件(A11y addon)使用 Axe 来审计当前 Story,并在插件面板中显示报告。快速查看即可确认我们的 Stories 中没有违反任何规则。

PR 检查

要捕获回归,您需要针对所有组件运行检查。您可以通过将 Stories 导入 Jest,然后使用jest-axe进行可访问性审计来实现。所有违规行为都将报告到 PR 页面。

交互测试

用户可以通过点击垃圾桶按钮来删除任务,我们需要添加一个测试来验证此行为。

开发过程中

在开发过程中,手动验证 InboxScreen Stories 中的交互。如果一切正常,您就可以开始使用 Jest 和 Testing Library 添加交互测试了。

// InboxScreen.test.js
import React from 'react';
import '@testing-library/jest-dom/extend-expect';
import {
 render,
 waitFor,
 cleanup,
 within,
 fireEvent,
} from '@testing-library/react';
import { axe, toHaveNoViolations } from 'jest-axe';
import { composeStories } from '@storybook/testing-react';
import { getWorker } from 'msw-storybook-addon';
import * as stories from './InboxScreen.stories';
 
expect.extend(toHaveNoViolations);
 
describe('InboxScreen', () => {
 afterEach(() => {
   cleanup();
 });
 
 afterAll(() => getWorker().close());
 
 const { Default } = composeStories(stories);
 
 it('should pin a task', async () => { ... });
 it('should archive a task', async () => { ... });
 it('should edit a task', async () => { ... });
 it('Should have no accessibility violations', async () => { ... });
 
 it('should delete a task', async () => {
   const { queryByText, getByRole, getAllByRole } = render(<Default />);
 
   await waitFor(() => {
     expect(queryByText('You have no tasks')).not.toBeInTheDocument();
   });
 
   const getTask = () => getByRole('listitem', { name: 'Export logo' });
 
   const deleteButton = within(getTask()).getByRole('button', {
     name: 'delete',
   });
 
   fireEvent.click(deleteButton);
 
   expect(getAllByRole('listitem').length).toBe(5);
 });

运行 yarn test 来确认所有测试都通过了。请注意 Jest 如何以 watch 模式运行,并且只执行与已更改文件相关的测试。

PR 检查

当 pull request 创建时,GitHub Actions 将运行 Jest 并通过 PR 检查报告状态。

用户流程测试

最后,您需要运行 E2E 测试,以确保所有关键用户流程都按预期工作。

开发过程中

您可以在开发过程中运行有针对性的 E2E 测试,但这需要您启动应用程序的完整实例和测试浏览器。这些都可能非常消耗资源。因此,除非您正在更新测试,否则可以在 CI 服务器上运行 Cypress。

PR 检查

与所有其他测试一样,GitHub Actions 也会使用 Cypress 运行 E2E 测试。

结论

开发人员 21% 的时间花在修复 bug 上。测试通过捕获缺陷并加快调试速度来帮助减少您的工作量。

但是每个新功能都会引入更多需要测试的 UI 和状态。要保持高效,唯一的方法就是实现一个直观的测试工作流。

首先将测试用例写成 Stories。您可以将它们重用于 Jest、Chromatic 和 Axe 等测试工具。研究表明,代码重用可以节省 42-81%的开发时间。

在开发过程中,边编码边测试以修复明显的 bug。这可以缩短您的反馈循环。它还可以防止 bug 进入生产环境,而修复生产环境中的 bug 的成本要高出 10 倍

最后,使用 CI 服务器对整个 UI 运行所有检查,以防止意外回归。

我希望将这些经验提炼成一个实用的工作流,能帮助您实现自己的稳健的测试策略。让这个工作流成为您的起点。

加入 Storybook 邮件列表

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

7,468开发者及更多

我们正在招聘!

加入 Storybook 和 Chromatic 团队。构建被数十万开发人员在生产中使用的工具。远程优先。

查看职位

热门帖子

Storybook 按需架构

构建的 Storybooks 减小 3 倍,加载速度提升更快
loading
Tom Coleman

交互式故事 (Beta 版)

使用 play 函数模拟用户行为
loading
Varun Vachhar

如何使用 Github Actions 自动化 UI 测试

加快您的工作流程,并交付更高质量的代码
loading
Varun Vachhar
加入社区
7,468开发者及更多
原因为什么选择 Storybook组件驱动的 UI
文档指南教程更新日志遥测
社区插件参与进来博客
展示探索项目组件词汇表
开源软件
Storybook - Storybook 中文

特别感谢 Netlify CircleCI