如何使用 React 18 和 Storybook 进行交互测试

唐裕
2023-12-01

在本文中,我们将专注于在使用 React 18 和 Storybook 时测试我们的组件的交互。在我们开始之前,您可能想阅读 Chak Shun Yu 的这篇介绍性文章,该文章探讨了 React 18 的新 API,以及宣布 React 18的博客文章,该文章深入了解了新的可选并发渲染功能反应 18。

  • 什么是交互测试?

  • Storybook 如何帮助进行交互测试?

  • Storybook 中测试组件的方法

  • 如何使用 Storybook 在 React 18 中执行交互测试

    • 如何使用交互插件更新您的 Storybook 配置

  • play使用 Storybook 和函数创建交互测试

    • 创建一个故事书组件

    • 创建我们组件的初始状态

    • 添加play功能

什么是交互测试?

交互测试涉及测试 React 组件内的交互。这些测试模拟应用程序中的用户操作,例如通过单击按钮或输入输入组件与组件交互,以及在此类交互之后应用程序的行为。

在现代应用程序中,组件比以前承担了更多的责任,因为开发人员已经开始在组件中包含诸如数据获取操作和状态管理工具之类的东西。2022 年 10 月微软已开始发布针对 Xbox One 和 Xbox Series X/S 游戏机的公开更新。通过交互测试,我们可以更有效地验证应用程序用户界面的功能方面。

Storybook 如何帮助进行交互测试?

Storybook是一个开源工具,可让您单独构建 UI 组件和页面。它允许您为组件构建文档,从而可以轻松重用组件并允许对它们进行可视化测试,这有助于防止错误。

要开始使用 Storybook,我们需要在现有项目的根目录中运行 Storybook CLI。如何修复 iPhone 14 性能问题,iPhone 14 性能问题解决方案在这种情况下,我们的项目是一个 React 应用程序,使用Create React App 创建。

运行以下命令,引导 React 应用程序并添加故事。

创建 React 应用程序:

npx create-react-app reactstorybook -template typescript
yarn start

打开另一个终端窗口并在我们项目的根目录中初始化 Storybook。

npx storybook init
yarn storybook

初始化完成后,Storybook 应该在本地启动并输出一个地址。根据您计算机的配置,Storybook 环境可能会在浏览器中自动打开。

故事是一个接受一组参数的组件,这些参数描述了如何呈现组件。它本质上捕获了 UI 组件的渲染状态。

在我们的 Create React 应用程序中初始化 Storybook 之后,Storybook 创建示例组件来演示可以使用 Storybook 构建的组件类型,即按钮、标题和页面。

示例组件概述了 Storybook 如何管理不同故事的状态。Stability AI 宣布向开源人工智能 AI 投资 1.01 亿美元Storybook UI 上显示的按钮组件的故事可以在我们的代码编辑器中找到。

在 React 应用程序的根目录中,打开终端窗口并输入以下命令以查看 Button 组件及其故事的代码。

code src/stories/Button.stories.tsx 
code src/stories/Button.tsx

Storybook 中的故事的一个关键重要性是使开发人员能够跟踪 UI 在进行更改时的外观。这有助于防止意外回归,Timothy Vernon 在他的帖子中对此进行了更多讨论,该帖子为开发人员提供了使用 Jest 处理视觉回归的测试策略。

Storybook 中测试组件的方法

Storybook 提供了一个单独测试组件的环境。测试已编写的故事很重要,因为它有助于防止随着时间的推移出现 UI 错误。


超过 20 万开发人员使用 LogRocket 来创造更好的数字体验了解更多 →


Storybook 附带了多种工具,可以测试 UI、模拟数据或依赖项,甚至模拟网络请求。测试运行器就是这样的工具之一。它使开发人员能够自动测试整个故事书并捕捉破碎的故事。

使用 Storybook 进行测试时,开发人员可以使用多种测试方法。

视觉回归测试

视觉回归测试有助于捕捉 UI 外观中的错误。它通过截取每个故事的屏幕截图并比较它们以识别变化来工作。Storybook 非常适合运行可视化测试,因为每个故事都是测试规范。

视觉回归测试不应与快照测试混淆,因为快照通过将每个故事的渲染标记与已知基线进行比较来工作。iPadOS 16将于2022年10月24日发布!苹果iPadOS16.1新功能即将推出快照测试不如视觉回归测试准确,因为它们比较的是 HTML 的 blob,而不是显示给用户的内容。这可能会导致误报,因为代码更改不会产生视觉变化。

可访问性测试

质量保证专业人员依靠可访问性测试来捕获在应用程序开发期间已提交的可访问性变化。可访问性测试依赖于Web 内容可访问性指南(WCAG) 规则来审核呈现的 DOM。如果呈现的 DOM 中的元素不符合 WCAG 规则,则会引发可访问性违规。

Storybook 提供了一个非常方便的工具,用于测试带有a11y 插件的应用程序的可访问性。

如何使用 Storybook 在 React 18 中执行交互测试

现在,是时候看看在 Storybook 和 React 18 中交互测试是如何工作的了。

如前所述,交互测试测试与 React 组件的交互。在交互测试中,目标是伪装成用户,这涉及到诸如键入和单击按钮等操作,并确保收到预期的输出。

React 组件的主要目标是在给定一组 props 的情况下渲染 UI,但也有一些复杂的组件可以跟踪应用程序状态。

Storybook 6.4 版中包含的play功能会在加载故事后执行。该play功能是测试我们组件的关键;使用该play功能,您可以模拟用户的行为。然后可以使用测试运行程序来确认组件是否正确呈现并检查与play函数的交互测试是否通过。

您需要安装两个关键软件包才能使其正常工作:

  • @storybook/testing-library : React 测试库的 Storybook 集成

  • @storybook/jest : Jest的 Storybook 集成,JavaScript 测试解决方案

在我们项目的根目录中打开终端,安装列出的包。


来自 LogRocket 的更多精彩文章:

  • 不要错过来自 LogRocket 的精选时事通讯The Replay

  • 了解LogRocket 的 Galileo 如何消除噪音以主动解决应用程序中的问题

  • 使用 React 的 useEffect优化应用程序的性能

  • 在多个 Node 版本之间切换

  • 了解如何使用 AnimXYZ 为您的 React 应用程序制作动画

  • 探索 Tauri,一个用于构建二进制文件的新框架

  • 比较NestJS 与 Express.js


yarn add -dev @storybook/testing-library @storybook/jest @storybook/test-runner jest@27

如果您使用的是旧版本的 Storybook,请检查您的package.json以确认该软件包@storybook/addon-interactions在devDependencies. 如果不是,请安装带有--dev标志的包,因为它对于在 Storybook 中设置交互测试是不可或缺的。

如何使用交互插件更新您的 Storybook 配置

module.exports = {
  stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-interactions", // Addon has to be registered
    "@storybook/preset-create-react-app",
  ],
  features: {
    interactionsDebugger: true, // enable playback controls
  },
  framework: "@storybook/react",
  core: {
    builder: "@storybook/builder-webpack5",
  },
};

play使用 Storybook 和函数创建交互测试

该play函数保存测试的逻辑,并连接到我们要测试的故事。让我们看看如何使用 Storybook 和play函数设置交互测试。

我们依靠@storybook/testing-libraryand@storybook/jest包来帮助解决这个问题。

创建一个故事书组件

为了体验幕后发生的事情,我们将创建一个具有两种状态的表单组件:

  1. 表单没有输入的一种状态

  2. 由函数处理的一种状态,play用于使用交互填充输入

在stories目录中,创建文件Form.tsx和Form.stories.tsx.

touch src/stories/Form.tsx
touch src/stories/form.css
touch src/stories/Form.stories.tsx

Form.tsx是我们的第一个组件。在该文件中,粘贴以下代码:

import React from "react";
import { Button } from "./Button";
import "./form.css";
​
interface FormProps {
  placeholder?: string;
  label?: string;
  name?: string;
}
​
export const Form = ({
  placeholder = "Enter your email",
  ...props
}: FormProps) => {
  const [details, setDetails] = React.useState(false);
​
  const onClick = () => {
    setDetails(true);
  };
​
  return (
    <div className="form-wrapper">
      <input
        autoComplete="off"
        placeholder="Enter your email address"
        className={"storybook-input"}
        name="email"
        aria-label="email"
        id="email"
        data-testid="email"
        {...props}
      />
      <input
        autoComplete="off"
        placeholder="Enter your password"
        className={"storybook-input"}
        name="password"
        id="password"
        data-testid="password"
        {...props}
      />
      <Button label="Submit" onClick={() => onClick()} />
      {details === true ? (
        <p>
          Get ready to experience great development experience with storybook
        </p>
      ) : (
        ""
      )}
    </div>
  );
};

创建我们的 CSS 文件。

code src/stories/form.css
.form-wrapper {
  padding: 5rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
  width: 30%;
}

创建我们组件的初始状态

现在,已经设置了父表单,是时候创建我们组件的初始状态了。让我们首先设置一个故事来设置表单的初始状态。

code src/stories/Form.stories.tsx
import React from "react";
import { ComponentStory, ComponentMeta } from "@storybook/react";
import { within, userEvent } from "@storybook/testing-library";
import { expect } from "@storybook/jest";
import { Form } from "./Form";

export default {
  title: "Example/Form",
  component: Form,
} as ComponentMeta<typeof Form>;

const Template: ComponentStory<typeof Form> = (args) => <Form {...args} />;

export const EmptyForm = Template.bind({});

export const InputedForm = Template.bind({});

在上面的代码块中,我们故事的基础部分已经构建好了。

添加play功能

是时候设置play在故事完成渲染后运行的函数了。使用该play功能,可以测试用户工作流程。

// the play function comes into use
InputedForm.play = async ({ canvasElement }) => {
  // start querying the component from its root element
  const canvas = within(canvasElement);

  // the key part, where the interactions are defined
  // Simulate interactions with the component
  await userEvent.type(canvas.getByTestId("email"), "due@email.com");

  await userEvent.type(canvas.getByTestId("password"), "a-due-password");

  await userEvent.click(canvas.getByRole("button"));

  // assert DOM structure
  await expect(
    canvas.getByText(
      "Get ready to experience great development experience with storybook"
    )
  ).toBeInTheDocument();
};

使用上面的代码块,我们已经设置了交互测试。userEvent模拟用户与组件的交互,即填写表单并提交表单。

我们将依靠test-runner来确认组件是否正确呈现。更新您的package.json脚本以启用测试运行器。

 "scripts": {
    "test-storybook": "test-storybook",
  },

使用以下命令运行测试运行程序。

yarn test-storybook

确认我们的测试通过后,我们可以导航到包含 Storybook UI 组件的浏览器窗口,以观察实际的交互测试。

Storybook 中的交互测试类似于测试库的用户事件 API。如果您使用用户事件 API,您将获得使用该fireEvent方法执行浏览器交互的高级模拟的能力。

结论

构建复杂的 UI 可能是一项困难的活动,尤其是在多个团队成员之间进行开发时。但是使用 Storybook 构建 UI 非常重视构建小型原子组件,这意味着可以更有效地测试组件。

可视化测试是 Storybook 擅长的领域之一,借助新的交互测试工具,我们可以轻松地看到 Storybook 生态系统的强大程度。

 类似资料: