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

介绍

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

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

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

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

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

先决条件

要完成本教程,您需要:

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

本教程已通过 Node v14.7.0、npmv6.14.7、reactv16.13.1 和jestv24.9.0 验证。

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

首先,为了进行测试,您需要使用Create React App创建一个React App在本教程中,该项目将被称为react-snapshot-tests

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

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

然后,切换到新创建的应用程序目录:

  • cd react-snapshot-tests

接下来,启动应用程序:

  • npm start

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

就本教程而言,您将要创建的组件会渲染items它接收到的道具。

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

  • 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为以下内容:

源代码/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 步 – 编写快照测试

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

  • 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没有项目作为 props 传递组件:

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,则可以运行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 主题页面以获取练习和编程项目。

觉得文章有用?

点个广告表达一下你的爱意吧 !😁