如何使用Jest为React组件编写快照测试

来自菜鸟教程
跳转至:导航、​搜索

介绍

快照测试允许您确保您的输出继续按预期运行。 这很有用,因为随着时间的推移,当您重新访问代码以进行更新时,这些更改可能会导致某些东西中断的可能性增加。

与严格的测试驱动开发 (TDD) 不同,标准做法是先编写失败的测试,然后编写代码以使测试通过,快照测试采用不同的方法。

在为 React 组件编写快照测试时,首先需要让代码处于工作状态。 然后,在给定特定数据的情况下生成其预期输出的快照。 快照测试与组件一起提交。 Jest 是一个测试框架,它将快照与测试的渲染输出进行比较。

如果测试失败,这可能意味着两件事。 如果测试结果出乎意料,您可能需要解决组件的问题。 如果测试结果符合预期,则可能意味着需要更新快照测试以支持新输出。

在本教程中,您将探索快照测试以及如何使用它们来确保您的用户界面 (UI) 不会意外更改。

先决条件

要完成本教程,您需要:

  • Node.js 安装在本地,您可以按照【X57X】如何安装Node.js 并创建本地开发环境【X126X】进行。
  • 熟悉 ReactJest 可能会有所帮助,但不是必需的。

本教程还使用 Visual Studio Code 作为代码编辑器,方便运行集成终端。 但是,您可以将其替换为您选择的编辑器和终端。

本教程已使用 Node v14.7.0、npm v6.14.7、react v16.13.1 和 jest v24.9.0 进行了验证。

第 1 步——创建一个 React 组件进行测试

首先,为了测试一些东西,你需要使用 Create React App 创建一个 React App。 对于本教程,项目将被称为 react-snapshot-tests

打开终端并运行以下命令:

npx create-react-app@3.4.1 react-snapshot-tests

然后,切换到新创建的 app 目录:

cd react-snapshot-tests

接下来,启动应用程序:

npm start

此时,您现在应该运行了一个 React 应用程序,并且可以在 Web 浏览器中查看它。 接下来,您需要创建一个可以测试的组件。

出于本教程的目的,您将要创建的组件会渲染它接收到的 items 道具。

在您的终端中,在 src 下创建一个 components 子目录:

mkdir src/components

然后,创建一个 Items.js 组件:

nano src/components/Items.js

将以下代码添加到 Items.js

src/components/Items.js

import React from 'react';
import PropTypes from 'prop-types';

/**
 * Render a list of items
 *
 * @param {Object} props - List of items
 */
function Items(props) {
  const { items = [] } = props;

  // A single item in the list, render a span.
  if (items.length === 1) {
    return <span>{items[0]}</span>;
  }

  // Multiple items on the list, render a list.
  if (items.length > 1) {
    return (
      <ul>
        {items.map(item => <li key={item}>{item}</li>)}
      </ul>
    );
  }

  // No items on the list, render an empty message.
  return <span>No items in list</span>;
}

Items.propTypes = {
  items: PropTypes.array,
};

Items.defaultProps = {
  items: []
};

export default Items;

此代码将根据数量渲染 items 道具:

  • 如果有多个项目,项目将显示在无序列表中(<ul>)。
  • 如果有单个项目,则该项目将显示在 <span> 元素中。
  • 如果没有项目,将显示错误消息。

最后,更新 App.js 来渲染我们的组件:

nano src/App.js

App.js 的内容替换为以下内容:

src/App.js

import React, { Component } from 'react';
import Items from './components/Items';

class App extends Component {
  render() {
    const items = [
      'Shark',
      'Dolphin',
      'Octopus'
    ];
    return (
      <Items items={items} />
    );
  }
}

export default App;

如果您在浏览器中访问该应用程序,将会出现一个屏幕,其中列出了您在 App.js 中建立的值:

Output* Shark
* Dolphin
* Octopus

由于有多个items,所以显示为无序列表。

接下来,您将添加快照测试。

第 2 步 — 编写快照测试

首先,删除 Create React App 生成的 App.test.js 文件:

rm src/App.test.js

本教程不需要它。

接下来,安装 react-test-renderer,这是一个库,可让您将 React 组件渲染为 JavaScript 对象,而无需 DOM。

npm install react-test-renderer@16.13.1

让我们添加您的第一个测试。 首先,您将创建一个 Items.test.js 文件:

nano src/components/Items.test.js

编写一个渲染 Items 组件的测试,其中没有作为道具传递的项目:

src/components/Items.test.js

import React from 'react';
import renderer from 'react-test-renderer';

import Items from './Items';

it('renders correctly when there are no items', () => {
  const tree = renderer.create(<Items />).toJSON();
  expect(tree).toMatchSnapshot();
});

接下来,让我们运行测试。 Create React App 处理了设置测试的所有初始化:

npm test

您应该通过 "renders correctly when there are no items" 的测试:

当您第一次运行快照测试时,请注意在 __snapshots__ 目录中创建了一个新的快照文件。 由于您的测试文件被命名为 Items.test.js,因此快照文件被适当地命名为 Items.test.js.snap

Items.tests.js.snap 的内容应该类似于:

src/components/__snapshots__/Items.test.js.snap

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders correctly when there are no items 1`] = `
<span>
  No items in list
</span>
`;

此快照与组件的确切输出相匹配。

Jest 使用 pretty-format 使快照文件易于阅读。

您现在可以为其他两个场景创建测试,其中有一个项目和多个项目。

打开Items.tests.js

nano src/components/Items.test.js

添加以下代码行:

src/components/Items.test.js

// ...

it('renders correctly when there is a single item', () => {
  const items = ['one'];
  const tree = renderer.create(<Items items={items} />).toJSON();
  expect(tree).toMatchSnapshot();
});

it('renders correctly when there are multiple items', () => {
  const items = ['one', 'two', 'three'];
  const tree = renderer.create(<Items items={items} />).toJSON();
  expect(tree).toMatchSnapshot();
});

至此,您已经编写了三个测试:一个针对没有项目,一个针对单个项目,另一个针对多个项目。

重新运行测试:

npm test

所有三个测试都应该成功通过,现在您的 __snapshots__ 目录中将拥有三个快照。

接下来,您将通过更新快照测试来解决失败的测试。

第 3 步 — 更新快照测试

为了更好地理解为什么需要快照测试,您将对 Items 组件进行更改并重新运行测试。 这将模拟对开发中的项目进行更改时会发生的情况。

打开Items.js

nano src/components/Items.js

将类名添加到 spanli 元素:

src/components/Items.js

...
/**
 * Render a list of items
 *
 * @param {Object} props - List of items
 */
function Items(props) {
  const { items = [] } = props;

  // A single item in the list, render a span.
  if (items.length === 1) {
    return <span className="item-message">{items[0]}</span>;
  }

  // Multiple items on the list, render a list.
  if (items.length > 1) {
    return (
      <ul>
        {items.map(item => <li key={item} className="item-message">{item}</li>)}
      </ul>
    );
  }

  // No items on the list, render an empty message.
  return <span className="empty-message">No items in list</span>;
}

Items.propTypes = {
  items: PropTypes.array,
};

Items.defaultProps = {
  items: [],
};

export default Items;

让我们重新运行测试:

npm test

您将观察到失败的测试结果:

Jest 将现有快照与具有更新更改的渲染组件匹配并失败,因为您的组件有一些添加。 然后它显示了引入快照测试的变化的差异。

如果更改不是预期的,您在部署更改之前发现了错误,现在可以解决该错误。 如果更改是预期的,您将需要更新您的快照测试以使它们正确通过。

对于本教程,您可以假设这是预期的更改。 您打算向组件添加类名。 然后,您应该更新快照测试。

当 Jest 处于交互模式时,您可以通过使用提供的选项按 u 来更新快照测试:

注意: 或者,如果你已经全局安装了 Jest [1],你可以运行 jest --updateSnapshotjest -u


这将更新快照以匹配您所做的更新,并且您的测试将通过。

这是之前没有项目的快照测试:

src/components/__snapshots__/Items.test.js.snap

//  ...

exports[`renders correctly when there are no items 1`] = `
<span>
  No items in list
</span>
`;

//  ...

这是新更新的无项目快照测试:

src/components/__snapshots__/Items.test.js.snap

//  ...

exports[`renders correctly when there are no items 1`] = `
<span
  className="empty-message"
>
  No items in list
</span>
`;

// ...

更新测试后,它们将通过:

您现在再次通过了测试。 如果这是一个正在开发的项目,您可以部署代码,因为您需要记录您想要的更改以供将来开发使用。

结论

在本教程中,您为 React 组件编写了快照测试。 您还修改了组件以经历失败的测试。 最后,您更新了快照以修复测试。

这是一个现场项目的小型模拟。 这个测试通过、失败和解决失败的循环将成为您的开发工作流程的一部分。

快照测试旨在成为许多不同的测试工具之一。 因此,您可能仍需要为您的操作和减速器编写测试。

当您探索了快照测试的基础知识时,您可以学到很多关于编写更好的快照测试的知识。 请查看 Jest 文档中的 Snapshot 最佳实践 ,以了解有关快照测试的更多信息。

如果您想了解有关 React 的更多信息,请查看 我们的 React 主题页面 以获取练习和编程项目。