花一个小时快速掌握Jest的所有知识点~

本文为稀土金块技术社区的第一篇署名文章。 14日内禁止转载,14日后禁止擅自转载。侵权必究!

大家好,我是小嘟嘟,我们知道常用的测试类型有: 功能测试 , 单元测试 , 集成测试 , 冒烟测试 等等,在哪里 单元测试 这是我们必须掌握的技术,所以让我们来看看为什么今天需要单元测试,作为一个 反应 开发人员需要掌握哪些技能?

如果您耐心阅读本章,您将学到以下内容:

  • 什么是单元测试?为什么我们需要它?
  • 如何做一个简单的单元测试?
  • Jest 有什么语法,Jest 的报告包含什么信息?
  • 如何兼容ts,需要什么配置?

同时附上今天的知识图,也请大家多多支持~

单元测试

有的朋友看到​​想聊 单元测试 ,可能会下意识地避免,因为 单元测试 比较麻烦,而且从某种角度来说也是比较麻烦的 无味 ,主要有以下几个原因:

1.对于大部分人来说,实际工作中是不需要的(需求写不出来,怎么可能写单元测试)

2. 语法相当于一门新语言,有一定的学习成本

3.配置虽然麻烦 入门文档看似很简单,但实际情况是:只要一个配置不合适,所有的测试都跑不起来,挺难受的。

以上几点可能是人们不想接触单元测试的主要原因,但是 单元测试 这确实是一个无法访问的 实用技巧 ,和一些开源产品一样,会有最基本的单元测试,所以 单元测试 是我们 先进的 不可或缺的一部分

什么是单元测试?

单元测试 : 指 原单位 对于单元,测试软件。

单元 一个函数 ,也可以是 一个模块 或者 一个组件 ,基本特征是只要输入不变,就必须返回相同的输出。

一个软件越容易进行单元测试,它的模块化结构就越好,模块之间的耦合就越弱。

我们都知道 反应 非常自由,它的组件化思维, 反应钩子 流行,非常适合单元测试

单元测试有什么好处?

首先我认为 单元测试 这是一项非常具有挑战性的工作,因为它要么成功,要么失败。在此期间,可能会出现各种问题。手动实现它更有利。接下来,让我们看看单元测试能给我们带来什么。有什么好处:

确保质量

单元测试可以有效防止我们减少 错误率

虽然 漏洞 我们无法避免,但没有人愿意 漏洞 很多,单元测试会让我们不得不思考一下 异常场景 ,这无形中增强了代码的 质量

描述代码

描述现有的代码,即 例子 作为记录。

比如有时候我们在写一个比较大的组件的时候,没有很好的例子来说明各个参数的作用,保证代码在各种情况下都能正常运行,单元测试可以 解读这段代码的含义 ,并且可以被其他开发者查看以增强代码 可读性

提升个人实力

抛开其他一切不谈,单元测试可以起到很大的推动作用 专业领域 .

第一的 单元测试 可以算作一个单独的字段,不同的框架需要不同的配置,如果依赖的组件发生变化,受影响的组件可能会出错。

其次,不同的环境,不同的测试框架会有一定的冲突(版本问题)

最后,可以模拟各种环境,并且 嘲笑 能力,例如: 反应 反应测试库 , 下一个 @nestjs/测试 等待

可以看出 单元测试 这是一个非常大的模块,也是一个值得研究的领域。一般来说, 利大于弊 ,想要进阶的请耐心阅读,相信一定会让你受益匪浅~

是的 Facebook 一个开源的前端测试框架,主要用于 反应 反应原生 单元测试,并集成在 创建反应应用 中间。

玩笑的特点

  1. 使用方便 :基于茉莉花,提供 断言库 , 支持多种测试风格
  2. 适应性 : 有 模块化的 , 可扩展 可配置
  3. 沙盒 快照 : Jest 内置了 JSDOM,可以 模拟浏览器环境 , 并并行执行
  4. 快照测试 : Jest 可以对 React 组件树进行操作 序列化 ,生成对应的字符串快照,通过字符串比较提供高性能的UI检测
  5. 模拟系统 : Jest 实现了一个强大的 Mock 系统并支持 自动的 手动模拟
  6. 支持异步代码测试 :支持 承诺 异步/等待
  7. 自动生成静态分析结果 : 内置 伊斯坦布尔 ,测试代码覆盖率,并生成相应的报告

第一个测试程序

初始化项目

 mkdir is-test  
 cd is-test  
  
 // 初始化 package.json 文件  
 npm 初始化 -y  
  
 // 安装是  
 npm 和 -D 是  
 复制代码

初始化是

 // 实施  
 npx 是 --init  
 复制代码

此时,会弹出一堆问题供您选择。当您选择时,将生成一个问题。 is.config.js ,这大约是 配置文件。

企业微信截图_5e351875-36fe-47b3-a5c9-06385e701d16.png

再看一遍 is.config.js 文档:

 模块。出口 = {  
 clearMocks:是的,  
 收集覆盖:真实,  
 覆盖目录:“覆盖”,  
 覆盖提供者:“v8”,  
 };  
 复制代码

例子

我们在目录中创建 src/sum.js 文件和 src/sum.test.js 文档

 // src/sum.js  
 常量总和 = ( a, b) => {  
 返回 a + b;  
 }  
  
 模块。出口=总和;  
  
 // src/sum.test.js  
 const sum = require('./sum');  
  
 描述('总和',()=> {  
 it('总和:1 + 2 = 3', () => {  
 期望(总和(1, 2))。等于(3);  
 });  
 })  
 复制代码

实施

此时,我们可以执行命令

 // npx 是  
 npm 运行测试  
 复制代码

你可以看到信息

image.png

单独执行

当我们的项目比较大的时候,我们只需要测试当前文件

 // npx 是  
 npm run test 文件路径  
 复制代码

这里的文件路径是 相对路径 ,它会自动匹配相同格式的文件,例如:

image.png

Jest 配置说明

我们完成了一个简单的 测试一下,接下来我们讲解一下各个文件的配置模块,方便我们后面进行

配置文件

我们通过 npx 是 --init 生成一个 is.config.js 文件,这个文件是关于 配置文件

此外,您可以通过 npx 是 --help 查看全部 有cli 选项

由于要配置的字段太多,这里就介绍一些常用的配置。您可以查看特定字段: 配置有

三种方式

第一种:我们可以将配置文件写入 is.config.js ,它返回一个 目的 或一个 功能 ,喜欢:

 // 目的  
 从'jest'导入类型{配置};  
  
 常量配置:配置 = {  
 详细:真实,  
 ...  
 };  
  
 导出默认配置;  
  
 // 功能  
 从'jest'导入类型{配置};  
  
 导出默认异步 (): Promises< Config> => {  
 返回 {  
 详细:真实,  
 ...  
 };  
 };  
 复制代码

第二:可以像 包.json 配置相应的 json 文件,命名为: is.config.json , 喜欢:

 {  
 “保释”:1,  
 “详细”:真实,  
 ...  
 }  
 复制代码

第三种:直接写入 包.json 在,写在 , 如:

 {  
 ...  
 “是”: {  
 “详细”:是的  
 }  
 ...  
 }  
 复制代码

特定领域

基础领域

  1. clearMocks :type: boolean, default: false, 每次测试前自动清除模拟上下文
  2. 收集覆盖 : type: boolean, default: false, 是否开启 覆盖范围
  3. 覆盖目录 : type: string, default: undefined, 生成的coverage文件的文件位置
  4. 覆盖提供者 :type: string, babel (default)/v8, 指示应该使用哪个提供程序来检测代码以进行覆盖
  5. 最大并发 :type: number,默认值:5,一个数字,用于限制使用时允许并发运行的测试数量。
  6. 预设 : type: string, default: undefined, default field, 应该指向哪个文件,可以是文件包或路径,如安装 翻译
  7. 转换 :类型 目的\<string, pathToTransformer | [pathToTransformer, object]> ,默认: {"^. + \\. [jt] sx?$": "babel-is"} , 转换器,可以使用正则,来匹配路径
  8. 转换忽略模式 :类型: 大批<string> ,默认: ["/node_modules/", "\\.pnp\\.[^\\\/]+$"] ,一个正则表达式模式字符串数组,匹配转换前的所有源文件路径。如果文件路径与 任何 模式匹配,它不会被转换。
  9. 显示名称 : 类型:字符串 | object,默认:undefined,这个参数可以直接告诉测试属于哪个项目
  10. collectCoverageFrom :类型:数组,默认:未定义,
  11. 缓存目录 :类型:字符串,默认值: /tmp/<path> ,用于存放依赖信息缓存的目录。
  12. 测试超时 :类型:数字,默认:5000,测试默认超时
  13. 测试环境 : type: string, default: node, 用于模拟测试的测试环境,如果我们使用浏览器环境(如:document),我们可以使用 我在家 代替
  14. 测试匹配 :类型: 大批<string> ,用于匹配对应文件下的文件
  15. testPathIgnorePatterns :类型: 大批<string> ,默认: ["/node_modules/"] , 在检测过程中跳过一些文件

collectCoverageFrom

类型:array,默认:undefined,通过该参数可以设置收集哪些文件配置信息,如:

 从'jest'导入类型{配置};  
  
 常量配置:配置 = {  
 收集覆盖范围:[  
 '**/*.{ts,tsx}',  
 '!**/node_modules/**',  
 '!**/小贩/**',  
 ],  
 };  
  
 导出默认配置;  
 复制代码

此配置将收集 根目录 ts,ts 的所有文件

不匹配 **/node_modules/** 或者 **/小贩/** 文档

项目

类型:数组<string | ProjectConfig>, default: undefined,我们可以通过这个参数来配置我们的项目,当它会提供一组路径或者glob模式时,Jest会同时在所有指定的项目中运行测试。

Jest.png

例如:

 从'jest'导入类型{配置};  
  
 常量配置:配置 = {  
 项目:['<rootDir> ', '<rootDir> /例子/*'],  
 };  
  
 导出默认配置;  
 复制代码

这个配置可以在 根目录 在示例目录中 在每个文件夹中运行 Jest

另一个例子:

 常量配置:配置 = {  
 项目:[{  
 测试环境:'jsdom',  
 displayName: 'react-jest',  
 测试匹配:[`<rootDir> /react-jest/src/**/*.test.ts?(x)`],  
 testPathIgnorePatterns:['/node_modules/'],  
 缓存目录:`./node_modules/.cache/jest`,  
 测试超时:30000,  
 ...  
 }],  
 };  
 复制代码

就像上面这个,我们知道 默认环境是 节点 ,但我们是 反应是 如果环境期望是浏览器的环境,可以单独设置 反应是 下面的文件是 我在家 ,匹配 测试 ts 或者 tsx 文件,删除一些文件(例如 节点模块 ) 和其他一些配置

全局设置

我们通过 sum.test.js 文件,找到 描述 预计 ,但是我们没有介绍相应的功能,但是可以正常使用。为什么是这样?

实际上 将这些方法和对象注入到测试文件的 全球环境 ,所以我们不需要通过 进口 或者 要求

当然,如果一定要引用,可以这样引用:

 从 '@jest/globals 复制代码导入 {describe, expect, test}

我们主要讲6个主要方法,更多方法请参考: Jest-全局设置

描述

描述 :描述块,将一组功能相关的测试用例组合在一起

用法: 描述(名称,fn)

  • 姓名 :string,描述的话语
  • fn 😦) => void,将所有代码写入该函数

: 别名 测试 ,用来存放测试用例,可以说有几个 会有几个测试用例

用法: 它(名称,fn,超时) 或者 测试(名称,fn,超时)

  • 姓名 :字符串,测试名称
  • fn 😦) => void,包含测试所期望的函数
  • fn :数字,默认值: 5s , 可选, 测试超时

afterAll 和 beforeAll

毕竟 : 所有测试用例都被执行 背部 要执行的方法,如果传入的回调函数的返回值为 承诺 或者 发电机 , 将等待 承诺解决 再次继续执行。

之前所有 : 和 毕竟 相反,所有测试用例都执行 向前 执行方法

用法: 毕竟(fn,超时)

  • fn 😦) => void,执行的函数
  • 暂停 :数字,默认值: 5s , 可选, 测试超时

afterEach 和 beforeEach

在每个之后 : 还 毕竟 相比, 在每个之后 可以在每个测试中完成 背部 到处跑

之前每个 之前每个 可以在每次测试后完成 向前 到处跑

用法: afterEach(fn, 超时)

  • fn 😦) => void,执行的函数
  • 暂停 :数字,默认值: 5s , 可选, 测试超时

例子

为了更好的理解,我们简单写一个例子,比如:

 const sum = require('./sum');  
  
 之前所有(()=> {  
 安慰。 log('全局之前');  
 });  
  
 毕竟(()=> {  
 安慰。 log('全局之后');  
 });  
  
 之前每个(()=>{  
 安慰。 log('在全局之前,每个都会执行');  
 });  
  
 之后(()=> {  
 安慰。 log('全局后,每个都会执行');  
 });  
  
 描述('总和',()=> {  
 之前所有(()=> {  
 安慰。 log('总和:在全局之前');  
 });  
    
 毕竟(()=> {  
 安慰。 log('求和:在全局之后');  
 });  
    
 之前(()=> {  
 安慰。 log('Sum: global before each will execute');  
 });  
    
 之后(()=> {  
 安慰。 log('求和:全局后,每一个都会被执行');  
 });  
  
 it('总和:1 + 2 = 3', () => {  
 期望(总和(1, 2))。等于(3);  
 });  
  
 it('总和:2 + 5 = 7', () => {  
 期望(总和(2, 5))。等于(7);  
 });  
 })  
 复制代码

结果:

企业微信截图_956e1ea2-fcf7-4720-b81f-e83b1a77b4d1.png

断言

断言 :expect,我们在测试一个结果是否满足的时候,经常需要判断,比如上面的 期望(总和(1, 2)).toEqual(3) 只是为了验证,执行后 求和函数 之后,结果是否等于 3

接下来,我们来看看一些常见的断言,细节: 期待断言

基本断言

  1. 期望(值) : 当你想测试一个值的断言时,首先用expect包装这个值
  2. 不是 :用于测试相反的结果,即不等于
  3. toMatch(正则表达式或字符串) :用于检查字符串是否匹配,可以 正则表达式 或者 细绳
  4. 包含(项目) :用于判断item是否在数组中,也可以用于判断字符串
  5. toBeNull(值) : 只匹配 null
  6. toBeUndefined(值) : 只匹配未定义
  7. toBeGreaterThan(数字) : 超过
  8. toBeGreaterThanOrEqual(数字) : 大于或等于
  9. toBeLessThan(数字) : 少于
  10. toBeLessThanOrEqual(数字) : 小于或等于
  11. toBeInstanceOf(类) : 判断是否是类的实例
  12. 任何东西(价值) : 匹配除 null 和 undefined 之外的所有值
  13. toHaveBeenCalled() : 用于判断mock函数是否被调用
  14. toHaveBeenCalledTimes(数字) :用于确定mock函数被调用的次数
  15. 断言(数量) :验证在测试用例中调用的断言数量

toBeUndefined 和 toBeDefined

toBeUndefined() : 用于检查变量是否未定义,即只会匹配 不明确的 ,例如上面的 返回的结果显然不是 不明确的 ,如果使用,会报错

被定义为() :与toBeUndefined相反,必须匹配的有值大小写

喜欢:

 描述('总和',()=> {  
 it('总和:1 + 2 = 3', () => {  
 期望(总和(1, 2))。 toBeUndefined(); //错误  
 });  
  
 it('总和:1 + 2 = 3', () => {  
 期望(总和(1, 2))。被定义为(); // 好的  
 });  
 })  
 复制代码

成为和平等

成为(价值) : 使用 Object.is 进行比较, 严格比较 ,需要注意的是,如果 浮点数 比较,使用 接近于 , 可以理解为 ===

等于(值) : 对于对象 深度 ,一般比较的是对象的值,而不是对象本身

所以 成为 等于 有什么区别?我们一起来看看:

对于基本类型:字符串、数字、布尔值等, 成为 等于 没有区别,区别主要在对象上,比如:

 常量数据1 = {  
 name: '小嘟嘟',  
 年龄:7,  
 };  
 常量数据2 = {  
 name: '小嘟嘟',  
 年龄:7,  
 };  
 复制代码

看得见 数据1 数据2 有平等的 姓名 年龄 ,所以 数据1 === 数据2 ?

很明显,它们是不相等的,原因是:它们指向不同,所以当我们使用 成为 错误,这是正常的

但是我们现在不是在比较地址,而是在比较 数据1 数据2 的每一项是否相等,则使用 等于 , 换句话说, 等于 将忽略两个对象的指针,只比较值,实心:

 它('toEqual',()=> {  
 期望(数据1)。等于(数据2); //好的  
 });  
    
 它('成为',()=> {  
 期望(数据1)。成为(数据2); // 错误  
 });  
 复制代码

做真实和做假

当我们不关心返回什么时,我们只关心返回值是真还是假。 说实话 (真实)和 虚假 (错误的)

让我们看下面的例子:

 常量数据 = ( 计数) => {  
 如果(类型计数 === '数字'){  
 返回计数  
 }  
 返回未定义  
 }  
  
 describe('Test toBeTruthy and toBeFalsy', () => {  
 它('toBeTruthy',()=> {  
 期望(数据(9))。 toBeTruthy(); // 好的  
 });  
 它('toBeFalsy', () => {  
 期望(数据('小嘟嘟'))。 toBeFalsy(); // 好的  
 });  
 它('toBeTruthy === 0', () => {  
 期望(数据(0))。 toBeTruthy(); // 错误  
 });  
 });  
 复制代码

什么时候 数据 当函数是数字时,它会返回 数字 , 对于其他类型将统一返回 不明确的

那么对应的,如果是数字,就是真值, toBeTruthy() 会被验证

如果不是数字, toBeFalsy () 将通过测试, toBeTruthy() 不会通过

但是当数字为0时,返回为0, toBeTruthy() 它也不会通过,你要注意这一点,here 假值 指: 错误的 , 0 , 无效的 , “” , 不明确的 六种类型

测试异步代码

先看一下这段异步代码:

 常量 fetchData = ( 标志 = true) => {  
 返回新的承诺((解决,拒绝)=> {  
 如果(标志){  
 resolve('小嘟嘟')  
 } 别的{  
 reject('错误你应该选择拒绝')  
 }  
 })  
 }  
 复制代码

我们如何测试这段代码?这里有三种方式

然后方式

 它('然后方式',()=> {  
 返回获取数据()。然后(数据=> {  
 期望(数据)。 toBe('小嘟嘟');  
 })  
 });  
 复制代码

异步等待方法

 it( '解决方法', () => {  
 期望(fetchData())。解决。 toBe('小嘟嘟');  
 });  
 复制代码

解决和拒绝

解决拒绝 : 主要用于 承诺 为了 解决/拒绝 包装值,并支持链接

喜欢:

 it( '解决方法', () => {  
 期望(fetchData())。解决。 toBe('小嘟嘟');  
 });  
  
 it( '拒绝方式', () => {  
 期望(取数据(假))。拒绝。 toMatch('错误');  
 });  
 复制代码

覆盖报告

终端上的结果

接下来我们看上面的例子,运行 npx 是 的结果

image.png

  • %stmts :是的 报表覆盖率 , 每个语句都执行了吗?
  • %分支 :是的 分支覆盖 , 是每一个 if 块执行
  • %功能 :是的 功能覆盖 , 是否每个函数都被调用
  • %行 :是的 线路覆盖 ,每一行都执行了吗?

报告文件

记住第一个 覆盖目录:“覆盖” ?

其实终端显示的信息只是一部分,生成的 覆盖范围 文件生成许多覆盖文件,包括: XML , JSON , HTML 等等,当然这些文件的内容是一样的,只是为了提取不同的工具,我们看一下文件目录:

image.png

然后我们打开 sum.js.html 查看结果

image.png

构建环境

因为 TS 迅速崛起,我们倾向于在我们的项目中使用 TS ,那么如何配置呢?
(是的 TS 不知道的可以看看这篇文章: 让你充分使用 TS 的指南 )

首先,请记住: 开玩笑,本机不支持翻译 ,所以我们需要通过其他的转译器来帮助我们

将第一个测试程序转化为ts

这里我们使用 做一个简单的变换,因为 被官方推荐

安装 ts

执行订单:

 npm i -D 打字稿  
 复制代码

安装后初始化ts的配置

 npx tsc --init  
 复制代码

会产生一个 tsconfig.json 文档

image.png

安装 ts-is

 npm 和 -D @types / is // 是类型  
 npm 和 -D ts-is // ts-is  
 复制代码

注意这里: jest的版本应该尽量一致(在major版本下) , 否则容易出现兼容性问题

配置

存在 is.config.js 文件添加:

 模块。出口 = {  
 预设:'ts-jest',  
 ...  
 };  
 复制代码

同时 tsconfig.json 加入

 {  
 “编译器选项”:{  
 “类型”:[“节点”,“笑话”],  
 ...  
 }  
 }  
 复制代码

最后,我们把 sum.js sum.test.js 改成 ts 文件

image.png

creat-react-app 集成了 jest

我们上面说了 集成在 创建反应应用 ,接下来我们看看它是如何集成的

创建一个程序

我们直接使用 创建反应应用 创造 ts 执行命令的程序

 npx create-react-app react-jest-test(sentence subject) --template typescript  
  
 cd react-is-test  
 npm i -D react-test-renderer //添加快照  
 复制代码

然后放 sum.ts sum.test.ts 复制到 源代码 在下面

模块化的

执行以下查看:

image.png

出现这个问题是因为不支持 进口 这个进口

解决方案:导入 babel-plugin-transform-es2015-modules-commonjs

 npm install --save-dev babel-plugin-transform-es2015-modules-commonjs  
 复制代码

然后在根目录下创建 .babelrc 文件,添加:

 {  
 “插件”:[“transform-es2015-modules-commonjs”]  
 }  
 复制代码

解决ts问题

然后我们再次运行它,看看:

企业微信截图_b019eb9c-b33c-4e14-8184-70b260ac6991.png

这个问题还是上面提到的翻译问题,我们需要补充 通天塔 ts 依赖

 npm i -D babel-jest @babel/core @babel/preset-env  
 npm i -D @babel/preset-typescript  
 复制代码

然后在以下目录中创建 babel.config.js 文件,添加:

 模块。出口 = {  
 预设:[  
 [  
 '@babel/preset-env',  
 {  
 目标:{  
 节点:'当前'  
 }  
 }  
 ],  
 '@babel/预设打字稿'  
 ]  
 };  
 复制代码

设置时要特别注意 babel.config.js 之后可能仍然无法正常工作,这是因为 通天塔 和设置有关,需要把扩展名改成 cjs , 那是, babel.config.cjs

至此配置成功

image.png

结尾

参考

总结

通过以上介绍,我们发现 实际上,它可以单独作为一个模块取出。我们全面介绍了相关 语法方便我们后续学习

当然 远不止于此。希望大家耐心阅读并试一试。在这里,希望大家能够充分熟悉这些概念,以方便后续的学习。 虚拟列表的自定义 Hooks,并详细解释如何进行单元测试 ,也希望各位小伙伴多多支持~

如果你喜欢它,请不要吝啬你的喜欢。如果大家有更好的建议,欢迎在评论区讨论,一起走进阶之路吧~

版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议。转载请附上原文出处链接和本声明。

这篇文章的链接: https://homecpp.art/4020/9523/1013

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/38158/57302011

posted @ 2022-09-20 11:57  哈哈哈来了啊啊啊  阅读(328)  评论(0编辑  收藏  举报