介绍
Snapshot 测试允许您确保您的输出继续按预期行为,这是有用的,因为当您重新浏览代码以进行更新时,这些更改可能会导致某些事情发生故障的可能性增加。
与严格的测试驱动开发(TDD)不同,其中标准做法是先写失败的测试,然后写代码来通过测试,即时测试采取了不同的方法。
在为 React 组件编写快照测试时,您首先需要在工作状态下进行代码。然后,根据某些数据生成预期输出快照。快照测试与组件一起进行。
在测试失败的情况下,这可能意味着两件事。如果测试结果是意想不到的,您可能需要解决您的组件的问题。如果测试结果是预期的,这可能意味着即时测试需要更新以支持新输出。
在本教程中,您将探索即时测试以及如何使用它们来确保您的用户界面(UI)不会意外改变。
前提条件
要完成本教程,您将需要:
- Node.js 本地安装,您可以按照 如何安装 Node.js 和创建本地开发环境进行操作。 *对 React和 Jest的一些熟悉可能是有益的,但不需要。
本教程还使用 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 应用程序。
打开终端并执行以下命令:
1npx [email protected] react-snapshot-tests
然后,更改到新创建的应用程序目录:
1cd react-snapshot-tests
接下来,开始应用程序:
1npm start
在此时刻,你现在应该有一个 React 应用程序运行,并可以在网页浏览器中查看它,然后你需要创建一个可以测试的组件。
对于本教程的目的,你要创建的组件会返回它所接收的项目
附加值。
在您的终端中,在src
下创建一个组件
子目录:
1mkdir src/components
然后,创建一个Items.js
组件:
1nano src/components/Items.js
将以下代码添加到Items.js
:
1[label src/components/Items.js]
2import React from 'react';
3import PropTypes from 'prop-types';
4
5/**
6 * Render a list of items
7 *
8 * @param {Object} props - List of items
9 */
10function Items(props) {
11 const { items = [] } = props;
12
13 // A single item in the list, render a span.
14 if (items.length === 1) {
15 return <span>{items[0]}</span>;
16 }
17
18 // Multiple items on the list, render a list.
19 if (items.length > 1) {
20 return (
21 <ul>
22 {items.map(item => <li key={item}>{item}</li>)}
23 </ul>
24 );
25 }
26
27 // No items on the list, render an empty message.
28 return <span>No items in list</span>;
29}
30
31Items.propTypes = {
32 items: PropTypes.array,
33};
34
35Items.defaultProps = {
36 items: []
37};
38
39export default Items;
此代码将根据金额显示项目
奖励:
- 如果有多个项目,则项目将显示在未分类的列表中(
<ul>
)。 *如果有一个项目,则该项目将显示在一个<span>
元素中 *如果没有项目,则会显示错误消息
最后,更新App.js
以使我们的组件:
1nano src/App.js
将App.js
的内容替换为以下内容:
1[label src/App.js]
2import React, { Component } from 'react';
3import Items from './components/Items';
4
5class App extends Component {
6 render() {
7 const items = [
8 'Shark',
9 'Dolphin',
10 'Octopus'
11 ];
12 return (
13 <Items items={items} />
14 );
15 }
16}
17
18export default App;
如果您在浏览器中访问应用程序,则会出现一个显示在App.js
中设置的值列表的屏幕:
1[secondary_label Output]
2* Shark
3* Dolphin
4* Octopus
由于有多个项目
,它将显示为未分类的列表。
接下来,您将添加您的快照测试。
步骤2 - 写 Snapshot 测试
要开始,请删除由 Create React App 生成的 App.test.js
文件:
1rm src/App.test.js
这个教程不需要它。
接下来,安装 react-test-renderer
,一个库,允许您将 React 组件渲染为 JavaScript 对象,而无需 DOM。
1npm install [email protected]
要开始,您将创建一个Items.test.js
文件:
1nano src/components/Items.test.js
编写一个测试,该测试将项目
组件转换为没有通过作为奖励的项目:
1[label src/components/Items.test.js]
2import React from 'react';
3import renderer from 'react-test-renderer';
4
5import Items from './Items';
6
7it('renders correctly when there are no items', () => {
8 const tree = renderer.create(<Items />).toJSON();
9 expect(tree).toMatchSnapshot();
10});
接下来,让我们运行测试 Create React App 处理了设置测试的所有初始化:
1npm test
你应该得到一个通过测试当没有项目时正确返回
:
当您首次运行快照测试时,请注意在__snapshots__
目录中创建一个新的快照文件,因为你的测试文件被命名为Items.test.js
,所以快照文件被适当命名为Items.test.js.snap
。
Items.tests.js.snap
的内容应该看起来像:
1[label src/components/__snapshots__/Items.test.js.snap]
2// Jest Snapshot v1, https://goo.gl/fbAQLP
3
4exports[`renders correctly when there are no items 1`] = `
5<span>
6 No items in list
7</span>
8`;
此快照与组件的精确输出相匹配。
它使用 pretty-format
来使快照文件可以人读。
现在,您可以创建两个其他场景的测试,其中有一个项目和多个项目。
打开Items.tests.js
:
1nano src/components/Items.test.js
添加以下代码行:
1[label src/components/Items.test.js]
2// ...
3
4it('renders correctly when there is a single item', () => {
5 const items = ['one'];
6 const tree = renderer.create(<Items items={items} />).toJSON();
7 expect(tree).toMatchSnapshot();
8});
9
10it('renders correctly when there are multiple items', () => {
11 const items = ['one', 'two', 'three'];
12 const tree = renderer.create(<Items items={items} />).toJSON();
13 expect(tree).toMatchSnapshot();
14});
在这个时候,你有三个测试写的:一个没有项目,一个单个项目,另一个多个项目。
重启测试:
1npm test
所有三个测试都应该顺利通过,你现在将在你的__snapshots__
目录中有三个快照。
接下来,您将通过更新快照测试来解决失败的测试。
步骤 3 – 更新 Snapshot 测试
为了更好地了解为什么您需要即时测试,您将引入项目
组件的更改,并重新运行测试,这将代表对正在开发中的项目进行更改时会发生什么的模拟。
打开Items.js
:
1nano src/components/Items.js
将类名称添加到span
和li
元素中:
1[label src/components/Items.js]
2...
3/**
4 * Render a list of items
5 *
6 * @param {Object} props - List of items
7 */
8function Items(props) {
9 const { items = [] } = props;
10
11 // A single item in the list, render a span.
12 if (items.length === 1) {
13 return <span className="item-message">{items[0]}</span>;
14 }
15
16 // Multiple items on the list, render a list.
17 if (items.length > 1) {
18 return (
19 <ul>
20 {items.map(item => <li key={item} className="item-message">{item}</li>)}
21 </ul>
22 );
23 }
24
25 // No items on the list, render an empty message.
26 return <span className="empty-message">No items in list</span>;
27}
28
29Items.propTypes = {
30 items: PropTypes.array,
31};
32
33Items.defaultProps = {
34 items: [],
35};
36
37export default Items;
让我们重启测试:
1npm test
您将看到失败的测试结果:
Jest 匹配了现有的截图与渲染的组件的更改,并未成功,因为您的组件有一些添加,然后显示了向截图测试引入的更改的差异。
如果更改未预期,则在部署更改之前您已经发现了错误,现在可以解决错误,如果更改预期,则需要更新您的快照测试以使其正确通过。
对于教程,您可以假设这是一个预期的变化. 您打算将类名称添加到组件中。
虽然 Jest 处于交互式模式,但您可以通过按u
按下提供的选项来更新快照测试:
<$>[注]
注: 另外,如果您有 Jest 全球安装,您可以运行 jest --updateSnapshot
或 jest -u
.
<$>
这将更新快照,以匹配您所做的更新,您的测试将通过。
以下是以前的没有项目的快照测试:
1[label src/components/__snapshots__/Items.test.js.snap]
2// ...
3
4exports[`renders correctly when there are no items 1`] = `
5<span>
6 No items in list
7</span>
8`;
9
10// ...
以下是对没有项目的新更新的快照测试:
1[label src/components/__snapshots__/Items.test.js.snap]
2// ...
3
4exports[`renders correctly when there are no items 1`] = `
5<span
6 className="empty-message"
7>
8 No items in list
9</span>
10`;
11
12// ...
更新测试后,他们将通过:
如果这是一个正在开发的项目,你可以部署代码,知道你打算的更改被记录在未来的开发。
结论
在本教程中,您为 React 组件撰写了即时测试,您还修改了组件以体验失败测试,最后您更新了即时测试以修复测试。
这个测试循环通过,失败,并解决失败将是您的开发工作流的一部分。
Snapshot测试是许多不同的测试工具之一,因此,您可能仍然需要为您的行动和减速器写测试。
虽然你已经探索了快照测试的基本知识,但你可以学到很多关于写更好的快照测试。 请从Jest的文档中查看 快照最佳实践以了解更多关于快照测试的信息。
如果您想了解更多关于 React 的信息,请参阅 我们的 React 主题页面以获取练习和编程项目。