在本教程中,我们将研究什么是快照测试,以及如何使用快照测试来确保我们的用户界面在团队不了解的情况下不会发生变化。

首先,您需要熟悉以下内容:

  1. NodeJS-基于Chrome的V8 JavaScript引擎构建的JavaScript运行时。
  2. React-一个JavaScript库,用于通过Facebook构建令人愉悦的UI。
  3. Jest-Facebook的JavaScript测试框架。

什么是快照测试?

与严格的“测试驱动开发”不同,在标准实践中,标准做法是先编写失败的测试,然后编写代码以使测试通过,而Snapshot测试则采用了另一种方法。

要编写快照测试,您首先需要使代码(例如React组件)正常工作,然后根据给定的数据生成其预期输出的快照。快照测试将在组件旁边以及每次运行时提交。 Jest将快照与测试的渲染输出进行比较。

如果测试未通过,则可能意味着您需要修复该组件上的某些意外更改,或者对该组件进行了某些更改,并且大约是在更新快照测试的时候了。

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

让我们开始吧!

创建一个简单的React组件

首先,我们将使用Create React App创建一个React App。

  • create-react-app ooh-snap
  • cd ooh-snap
  • yarn start

我们现在应该有一个React应用。让我们继续,创建一个可以测试的组件。我们将要创建的组件根据项目的数量将其接收的项目道具渲染为列表或span元素。

创建一个Components文件夹,然后添加以下Items组件:

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;

  if (!items.length) {
    // No Items on the list, render an empty message
    return <span>No items in list</span>;
  }

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

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

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

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

export default Items;

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

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

class App extends Component {
  render() {
    const items = [
      'Thor',
      'Captain America',
      'Hulk'
    ];
    return (
      <Items items={items} />
    );
  }
}

export default App;

实际上,删除App.test.js,因为我们将在下一部分中添加我们自己的测试。

接下来,让我们继续并添加快照测试。

编写快照测试

首先,请安装react-test-renderer,该库使您无需DOM就可以将React组件呈现为JavaScript对象。

  • yarn add react-test-renderer

让我们添加第一个测试。首先,我们将创建一个测试,该测试将渲染Items组件,并且不传递任何道具作为道具:

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,我们不需要设置其他任何东西即可运行我们的测试。

  • yarn test

首次运行测试时,请注意在__snapshots__目录中创建了一个新的快照文件。由于我们的测试文件名为Items.test.js,因此快照文件也相应命名为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使用漂亮格式使快照文件易于阅读。

如果掌握了这一点,请继续针对存在一个项目且存在多个项目的另外两种方案创建测试,然后运行测试。

...
it('renders correctly when there is one 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();
});

接下来,让我们对组件进行更新。

更新快照测试

要了解为什么需要进行快照测试,我们将继续并更新Items组件,然后重新运行测试。对于您的开发环境,这是对团队中某人进行组件更改并且您的CI工具运行测试时发生的情况的模拟。

我们将类名称添加到span和li元素,例如,以影响某些样式。

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

  if (!items.length) {
    // No Items on the list, render an empty message
    return <span className="empty-message">No items in list</span>;
  }

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

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

代替更改,让我们再次使用yarn test命令运行测试。

Jest用更新的更改将现有快照与呈现的组件进行了匹配,但是失败了,因为我们的组件有所增加。然后,它显示了快照测试中引入的更改的差异。

要解决此问题,无论出于何种原因,都将完全取决于快照测试中引入的更改。

如果不希望进行更改,那很好,您可以在不晚之前就已经做好了。如果需要进行更改,请更新快照测试,然后一切都变为绿色。

当Jest处于交互模式时,您可以通过使用提供的选项按u来更新快照测试。或者,您可以运行jest --updateSnapshot或jest -u。

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

继续并进入快照文件夹以查看快照文件如何更改。这是更新的空快照片段。

exports[`renders correctly when there is one item 1`] = `
<span
  className="item-message"
>
  one
</span>
`;

结论

在本教程中,我们已经能够为React组件编写快照测试。我们还更新了组件以查看失败的测试,并最终更新了快照以修复测试。

虽然我们已经介绍了快照测试的基础知识,但是在编写更好的快照测试方面您可以学到很多。请查看Jest文档中的“快照”最佳做法,以了解有关快照测试的更多信息。