使用React.js和Jest测试您的应用程序,如老板
在Twitter上关注我,很高兴听取您关于主题或改进的建议/ Chris
在本文中,我们将介绍测试框架Jest。我们将学习如何:
- 编写测试,在特定条件下编写测试和断言是一件轻而易举的事
- 通过利用模式匹配功能运行特定测试以及特定测试文件来管理我们的测试套件
- 调试我们的测试,通过扩充VS Code,我们可以获得在测试中设置断点的能力,并创建一个非常好的调试体验
- 快照掌握,了解如何使用快照可以让您更加放心,您的组件在更改后仍然可以正常工作
- 利用模拟,模拟依赖关系可以确保您只测试您想要测试的内容,而Jest在模拟方面具有很好的默认值
- 覆盖率报告,我们期望在所有优秀的测试库中包含一个良好的覆盖工具。 Jest也不例外,它很容易运行覆盖率报告并快速找到可以从更多测试中获益的代码部分
Jest通过说它来卖自己
令人愉快的JavaScript测试
令人愉快的是什么?它拥有零配置体验。
好的,我们越来越接近答案了。
- 由于工作人员,并行测试可以获得出色的性能。
- 内置覆盖工具
- 由于ts-jest,使用打字稿
开始吧
让我们尝试设置它,看看需要多少配置。如果您只是想尝试一下,有一个Jest REPL,您可以在其中编写测试。
写我们的第一个测试
为了让测试运行器找到测试,我们需要遵循三个约定之一:
- 创建一个
__tests__
目录并将文件放在那里 - 使文件匹配
* spec.js
- 使文件匹配
.test.js
好的,现在我们知道Jest将如何找到我们的文件,如何编写测试?
// add.js 功能 加(一个, b) { 返回 一个 + b; } 模。出口 = 加; // add.spec.js 常量 加 = 要求('../加'); 描述('加', () => { 它('应该添加两个数字', () => { 期望(加(1, 2))。成为(3); }); });
我们在上面看到我们正在使用 描述
创建测试套件并在测试套件中创建测试。我们也看到我们使用 期望
断言结果。该 期望
让我们访问了很多 匹配器
,匹配器是我们在期望之后调用的函数:
期待(某事).matcher(值)
正如您在我们的测试示例中所看到的,我们正在使用一个名为的匹配器 成为()
它基本上匹配期望内部匹配器内部的内容,例如:
期望(1)。成为(1) //成功 期望(2)。成为(1) //失败了
有很多匹配器,所以我恳请你看一下那些存在的并尝试使用适当的匹配器Matchers
运行我们的测试
我们可以做的最简单的事情就是使用创建项目 CREATE-反应应用内
因为Jest已经在那里设置了。一旦我们创建了项目并安装了所有依赖项,我们就可以运行:
纱线测试
它将显示上面的图像包含:
- 一个执行的测试套件,
- 一个通过测试和主机命令,我们将稍微探讨。它似乎运行了该文件
SRC / App.test.js
。
我们来看看上面的文件:
进口 应对 从 “反应”; 进口 ReactDOM 从 '反应-DOM'; 进口 应用 从 './App'; 它('渲染没有崩盘', () => { 常量 DIV = 文献。的createElement(“格”); ReactDOM。给予(<应用 />, DIV); ReactDOM。unmountComponentAtNode(DIV); });
我们可以看到它已经使用它创建了一个测试,并且还创建了一个使用的组件 ReactDOM.render(
然后通过电话清理自己 ReactDOM.unmount(DIV)
。我们现在还没有真正做过任何断言,我们刚刚尝试创建一个没有错误的组件,但这很好。
我们尝试添加怎么样? add.js
文件及其相应的测试?
我们先添加 add.js
,像这样:
// add.js 功能 加(一个,b) { 返回 一个 + b; } 出口 默认 加;
然后是测试:
// add.spec.js 进口 加 从 '../加'; 它('测试添加', () => { 常量 实际 = 加(1,3); 期望(实际)。成为(4); });
我们的Jest会话仍在终端中运行:
我们可以看到我们现在有两个通过测试。
调试
任何体面的测试运行器/框架都应该让我们能够调试我们的测试。它应该让我们有能力:
- 运行特定的测试
- 忽略测试
- 设置断点,让我们在IDE中添加断点(更多的是IDE供应商来实现这一点)
- 在浏览器中运行,让我们在浏览器中运行我们的测试
运行特定的测试文件
让我们看看如何做这些事情,让我们从运行特定的测试开始。首先,我们将添加另一个文件 subtract.js
和相应的测试。
// subtract.js 功能 减去(一个,b) { 返回 一个 - b; } 出口 默认 减去;
和测试:
// subtract.spec.js 进口 减去 从 '../减去'; 它('测试减去', () => { 常量 实际 = 减去(3,2); 期望(实际)。成为(1); });
让我们再看看我们的终端,尤其是它的底部:
如果你没有看到这个新闻 w ^
如屏幕上所示。以上为我们提供了一系列命令,使我们的调试更容易:
-
一个
,运行所有测试 -
p
,这将允许我们指定一个模式,通常我们想在这里指定一个文件的名称,使其只运行该文件。 -
Ť
,它与p相同但它允许我们指定测试名称 -
q
,退出手表模式 -
返回
,触发测试运行
鉴于以上描述,我们将尝试将其过滤以仅测试 add.js
文件,所以我们输入 p
:
这会将我们带到一个模式对话框,我们可以在其中输入文件名。我们这样做:
上面我们现在可以看到只有 add.js
文件将被定位。
运行特定测试
我们已经学会了如何将其缩小到特定文件。我们可以将其缩小到特定的测试,即使使用 p
,模式方法。首先,我们需要添加一个测试,以便我们可以实际过滤掉它:
//add.spec.js 进口 加 从 '../加'; 它('测试添加', () => { 常量 实际 = 加(1,3); 期望(实际)。成为(4); }); 它('测试添加 - 应该是否定的', () => { 常量 实际 = 加(-2,1); 期望(实际)。成为(-1); });
此时我们的终端看起来像这样:
所以我们在同一个文件中有两个通过测试,但我们只想运行一个特定的测试。我们这样做是通过添加 。只要()
打电话给考试,如下:
它。只要('测试添加', () => { 常量 实际 = 加(1,3); 期望(实际)。成为(4); });
终端现在看起来像这样:
我们可以看到添加 。只要()
如果我们只想运行该测试,那么工作得很好。我们可以用 。跳跃()
让测试运行器跳过特定的测试:
它。跳跃('测试添加', () => { 常量 实际 = 加(1,3); 期望(实际)。成为(4); });
结果终端明确表示我们跳过了测试:
使用断点进行调试
现在,这个有点依赖于IDE,对于本节,我们将介绍如何在VS Code中执行此操作。我们要做的第一件事是安装扩展。转到扩展菜单并搜索Jest。应显示以下内容:
安装此扩展程序并返回到您的代码。现在我们有了一些附加功能。我们所有的测试都应该有一个 调试链接
在每一次测试中。
此时,我们可以添加一个断点,然后按下我们的 调试链接
。您的断点现在应该被击中,它应该是这样的:
快照测试
快照是关于创建快照,是渲染组件时DOM的外观。它用于确保当您或其他人对组件进行更改时,快照会告诉您,您进行了更改,更改是否正常?
如果您同意所做的更改,则可以使用现在呈现的DOM轻松更新快照。因此快照是您的朋友,以保护您免受无意的更改。
我们来看看如何创建快照。首先,我们可能需要安装依赖项:
yarn add react-test-renderer –save
下一步是编写一个组件和一个测试来配合它。它应该看起来像这样:
// Todos.js 进口 应对 从 “反应”; 常量 待办事项 = ({ 待办事项 }) => ( <应对。分段> {待办事项。地图(去做 => <DIV>{去做}</ DIV>)} </React.Fragment> ); 出口 默认 待办事项; // Todos.spec.js 进口 渲染 从 “反应 - 测试 - 渲染”; 进口 应对 从 “反应”; 进口 待办事项 从 ” ../Todos'; 测试('Todo - 应创建快照', () => { 常量 零件 = 渲染。创建( <待办事项 待办事项={(“物品1”, 'ITEM2')} /> ); 让 树 = 零件。的toJSON(); 期望(树)。toMatchSnapshot(); })
注意如何导入, 进口
我们即将测试的组件:
从'../Todos'导入Todos;
然后使用渲染器创建组件的实例。下一步是将该组件转换为JSON表示,如此 component.toJSON()
最后,我们通过电话断言 期待(树).toMatchSnapshot()
,这将调用一个快照,将自己放在一个 __snapshots__
test目录下的目录。
管理快照
好的,所以我们有快照,现在是什么?让我们对todo组件进行更改,如下所示:
// Todos.js 进口 应对 从 “反应”; 常量 待办事项 = ({ 待办事项 }) => ( <应对。分段> { 待办事项。地图(去做 => ( <应对。分段> <H3>{去做。标题}H3> <DIV>{去做。描述}DIV> 应对。分段> ))} 应对。分段> ); 出口 默认 待办事项;
我们看到了我们的 去做
是一个对象而不是一个字符串,所以它有一个 标题
和 描述
属性。这将使我们的快照做出反应,它将说明以下内容:
它清楚地表明了一些不同的东西,并要求我们检查代码。如果我们对这些变化感到满意,我们应该按下 ü
将快照更新为新版本。所以看看代码,是的,这是一个预期的变化,所以我们按下 ü
。我们最终得到以下图片,告诉我们一切正常:
惩戒
模拟是需要运作良好的事情之一。在Jest中嘲弄很容易。您需要在与模块相邻的目录中创建模拟,或者更像是模块的子目录。让我们在代码中展示我的意思。想象一下,你有以下模块:
// repository.js 常量 数据 = ({ 标题: '来自数据库的数据' }); 出口 默认 数据;
让我们来看看这个测试:
// repository.spec.js 进口 数据 从 '../repository'; 描述('测试存储库数据', () => { 它('应该返回1项', () => { 安慰。日志(数据); 期望(数据。长度)。成为(1); }); });
不是最好的测试,但它是一个测试。让我们创建我们的模拟,以便我们的文件结构如下所示:
//目录结构repository.js //我们的repo文件__mocks __ / repository.js //我们的模拟
我们的模拟应该如下所示:
// __mock __ / repository.js 常量 数据 = ({ 标题: '模拟数据' }); 出口 默认 数据;
要使用此模拟,我们需要调用 jest.mock()
在我们的测试中,如下:
// repository.spec.js 进口 数据 从 '../repository'; 笑话。嘲笑('../repository'); //使用__mock / repository而不是实际的 描述('测试存储库数据', () => { 它('应该返回1项', () => { 安慰。日志(数据); 期望(数据。长度)。成为(1); }); });
现在它使用我们的模拟而不是实际的模块。好吧,你说,为什么我要嘲笑我要测试的东西。简短的回答是:你不会。因此,我们将创建另一个文件 consumer.js
用我们的 repository.js
。那么让我们来看看它的代码及其相应的测试:
// consumer.js 进口 数据 从 './repository'; 常量 项目 = { 标题: '消费者' }; 出口 默认 ( ...数据, { ...项目});
上面我们清楚地看到我们的消费者如何使用我 repository.js
现在我们想要模拟它,以便我们专注于测试消费者模块。我们来看看测试:
// consumer.spec.js 进口 数据 从 '../消费者'; 笑话。嘲笑('../repository'); 描述('测试消费者数据', () => { 它('应归还2件', () => { 安慰。日志(数据); 期望(数据。长度)。成为(2); }); });
我们用 jest.mock()
并嘲笑这个模块唯一的外部依赖。
像lib这样的 lodash
要么 jQuery的
,那些不是我们创建但依赖的模块的东西?我们可以通过创建一个来为最高级别的人创建模拟 __mocks__
目录。
关于模拟还有很多可以说的,有关详细信息,请查看文档Mocking docs
覆盖
我们已经到了本章的最后一节。这是关于实现测试涵盖了多少代码。要检查这一点,我们只需运行:
纱线测试覆盖率
这将为我们提供一个终端内部的表格,它将告诉我们每个文件的百分比覆盖率。它还会产生一个 覆盖
我们可以导航到的目录,并找到我们的报道的HTML报告。但首先让我们改变 add.js
文件添加一段需要测试的逻辑,如下所示:
// add.js 功能 加(一个, b) { 如果(一个 > 0 && b > 0 ) { 返回 一个 + b; } 扔 新 错误('参数必须大于零'); } 出口 默认 加;
现在我们可以看到我们在应用程序中有多条路径。如果我们的输入参数大于零,那么我们现有的测试覆盖它。
但是,如果一个或多个参数低于零,那么我们输入一个新的执行路径,并且测试不会覆盖该路径。让我们通过导航来看看覆盖率报告中的内容 报道/ LCOV报告
。我们可以通过输入来显示这个例子
http-server -p 5000
我们会得到一份如下所示的报告:
现在我们可以导航到 SRC / add.js
它看起来应该是这样的:
现在我们可以清楚地看到我们添加的代码如何用红色表示,我们需要添加一个测试来覆盖新的执行路径。
接下来,我们添加一个测试来覆盖这个,如下所示:
// add.spec.js 进口 加 从 '../加'; 描述('加', () => { 它('测试添加', () => { 常量 实际 = 加(1,2); 期望(实际)。成为(3); }); 它('使用neg数测试加法', () => { 期望(() => { 加(-1,2); })。toThrow('参数必须大于零'); }) }) )
我们的第二种情况现在应该涵盖导致异常被抛出的执行路径。让我们重新运行我们的报道:
摘要
我们已经看过如何编写测试。我们还研究了如何使用VS Code的扩展来调试我们的测试,这允许我们设置断点。
此外,我们已经了解了快照是什么以及如何最好地利用它们。
接下来我们一直在考虑利用模拟来确保我们在测试时完全隔离。
最后,我们研究了如何生成覆盖率报告以及它如何帮助您跟踪代码中可能真正受益于更多测试的部分代码。
进一步阅读
- Jest的官方文档可以在这里找到官方文档
- 我的免费React书