测试的意义是什么?
在编程术语中,测试意味着检查我们的代码是否符合某些期望。例如:一个名为 “ transformer” 的函数应在给定某些输入的情况下返回期望的输出。
测试类型很多,但简单来说测试分为三大类:
- 单元测试
- 集成测试
- UI 测试
在本 Jest 教程中,我们将仅介绍单元测试,但是在本文结尾,您将找到其他类型的测试的资源。
Jest 教程:什么是 Jest
Jest 是 JavaScript 测试运行程序,即用于创建,运行和构建测试的 JavaScript 库。Jest 是作为 NPM 软件包分发的,您可以将其安装在任何 JavaScript 项目中。 Jest 是目前最受欢迎的测试运行程序之一(我觉得没有之一),也是 Create React App 的默认选择。
首先,我怎么知道要测试什么?
在测试方面,即使是简单的代码块也可能使新手懵逼。最常见的问题是 “我怎么知道要测试什么?”。如果你正在编写 Web 应用程序,那么一个好的切入点就是测试应用程序的每个页面以及每个用户的交互。但是,Web 应用程序也由功能和模块之类的代码单元组成,也需要进行测试。大多数情况下有两种情况:
- 你继承了未经测试的旧代码
- 你从 0 开始新实现的功能
该怎么做呢?对于这两种情况,你都可以通过将测试视为代码的一部分来进行检查,这些代码可以检查给定的函数是否产生预期的结果。典型的测试流程如下所示:
- 导入到测试的功能
- 给定一个输入
- 定义期望的输出
- 检查函数是否产生预期的输出
真的,就是这样。如果你从以下角度考虑,测试将不再可怕:输入-预期输出-声明结果。稍后,我们还将看到一个方便的工具,用于几乎准确地检查要测试的内容。现在先用 Jest 手动测试!
Jest 教程: 初始化项目
与每个 JavaScript 项目一样,您将需要一个 NPM 环境(确保在系统上安装了 Node)。创建一个新文件夹并使用以下命令初始化项目:
1 2 |
mkdir getting-started-with-jest && cd $_ npm init -y |
下一步安装 Jest:
1 |
npm i jest --save-dev |
我们还需要配置一个 script,以便从命令行运行测试。打开 package.json 并配置名为 “ test” 的脚本以运行 Jest:
1 2 3 |
"scripts": { "test": "jest" }, |
现在,你可以嗨皮的开始(入坑)了。
Jest 教程:规范和测试驱动的开发
作为开发人员,我们都喜欢创造自由。但是,当涉及到严重的问题时,大多数时候没有那么多特权。通常,我们必须遵循规范,即对构建内容的书面或口头描述。
在本教程中,我们的项目经理提供了一个相当简单的规范。非常重要的一点是,业务方需要一个 JavaScript 函数,该函数用来过滤一个对象数组。
对于每个对象,我们必须检查一个名为 “ url” 的属性,如果该属性的值与给定的关键字匹配,则应在结果数组中包括匹配的对象。作为一个精通测试的 JavaScript 开发人员,你希望遵循 TDD(测试驱动开发),这是一种在开始编写代码之前必须编写失败测试的准则。
默认情况下,Jest 希望在项目文件夹中的 “ tests” 文件夹中找到测试文件。
创建新文件夹:
1 2 |
cd getting-started-with-jest mkdir __tests__ |
接下来,在 __tests__
目录中中创建一个名为 filterByTerm.spec.js 的新文件。你可能想知道为什么扩展名包含 “ .spec”。这是从 Ruby 借来的约定,用于将文件标记为给定功能的规范。
现在,让我们进行测试!
Jest 教程:测试结构和第一个失败的测试
是时候创建你的第一个 Jest 测试了。打开 filterByTerm.spec.js 并创建一个测试块:
1 2 3 |
describe("Filter function", () => { // test stuff }); |
我们的第一个朋友 describe, 一种用于包含一个或多个相关测试的 Jest 方法。
每次在开始为功能编写新的测试套件时,都将其包装在 describe 块中。
如你所见,它带有两个参数:用于描述测试套件的字符串和用于包装实际测试的回调函数。
接下来,我们将遇到另一个称为 test 的函数,它是实际的测试块:
1 2 3 4 5 |
describe("Filter function", () => { test("it should filter by a search term (link)", () => { // actual test }); }); |
至此,我们准备编写测试了。请记住,测试是输入,功能和预期输出的问题。首先让我们定义一个简单的输入,即对象数组:
1 2 3 4 5 6 7 8 |
test("it should filter by a search term (link)", () => { const input = [ { id: 1, url: "https://www.url1.dev" }, { id: 2, url: "https://www.url2.dev" }, { id: 3, url: "https://www.link3.dev" } ]; }); }); |
接下来,我们将定义预期的结果。根据规范,被测函数应忽略其 url 属性与给定搜索词不匹配的对象。例如,我们可以期望一个带有单个对象的数组,给定 “link” 作为搜索词:
1 2 3 4 5 6 7 8 9 10 11 |
describe("Filter function", () => { test("it should filter by a search term (link)", () => { const input = [ { id: 1, url: "https://www.url1.dev" }, { id: 2, url: "https://www.url2.dev" }, { id: 3, url: "https://www.link3.dev" } ]; const output = [{ id: 3, url: "https://www.link3.dev" }]; }); }); |
现在我们准备编写实际的测试。我们将使用 expect 和 Jest 匹配器来检查虚拟函数(目前)在调用时是否返回了预期结果。这是测试:
1 |
expect(filterByTerm(input, "link")).toEqual(output); |
为了进一步分解内容,这是在代码中调用该函数的方式:
1 |
filterByTerm(inputArr, "link"); |