前端测试框架—jest基本使用

  • 前言
  • jest
  • 常见匹配器
    • 基本类型
    • boolean
    • Number
    • String
    • Array,Set
    • 异常
    • 取反
  • 命令行工具使用
  • 异步代码测试方法
  • 钩子函数
  • 分组(钩子函数从外往内执行)
  • mock
  • snapshot 快照测试
  • mock -- timers定时器
  • ES6 中类的测试
  • 总结

前言

最近想着做一个UI组件库,然后发现做一个UI组件库所需要的技术还是比较多的,比如前端测试,自动化部署,打包构建等等。所以我首先定他一个小目标,先从前端测试开始学起,然后我在网上找了一些关于前端测试的视频和资料,学了三个星期算是入门了,所以打算整理一下我在学习过程中记录下来的笔记,方便日后查看,我这里学习的测试框架主要是jest

jest

常见匹配器

基本类型

  • toBe :引用值相等
  • toEqual :内容相等
  • toBeNull :为空
  • toBeUndefined :undefined
  • toBeDefined :已定义

boolean

  • toBeTruthy :为真
  • toBeFalsy :为假

Number

  • toBeGreaterThan :大于
  • toBeLessThan :小于
  • toBeGreaterThanOrEqual :大于等于
  • toBeCloseTo :小数点运算

String

  • toMatch :字符串匹配

Array,Set

  • toContain :包含

异常

  • toThrow : 会抛出异常

取反

  • not :相反

命令行工具使用

  • f模式 :只运行失败的测试用例
  • o模式 :只运行被修改文件的测试用例(该模式必须结合git仓库才能使用,–watch)
  • a模式 :重新运行所有测试用例(–watchAll)
  • t模式 :只运行匹配的测试用例
  • p模式 :只运行匹配的文件名下的所有测试用例

异步代码测试方法

  • 回调类型异步函数
// fetch.js
import axios from 'axios'
const url = 'http://xxx/demo.json';
export function fetchData(fn) {axios.get(url).then(res=>{fn(res.data)})
}// fetch.test.js
import {fetchData} from "./fetch";test('回调类型异步函数测试',(done)=>{fetchData((data)=>{expect(data).toEqual({success:true});done();})
});
  • promise异步函数测试
// fetch.js
import axios from 'axios'
const url = 'http://xxx/demo.json';
export function fetchData() {return axios.get(url)
}// fetch.test.js
/*** 注意2点* 1、test的第二个函数不能写done参数* 2、必须return*/
test('promise异步函数测试',()=>{return fetchData().then(res=>{expect(res.data).toEqual({success:true})})
});
test('promise异步函数测试,并且返回404', () => {return expect(fetchData()).rejects.toThrow();
});
//=========================
test('promise异步函数测试', () => {return expect(fetchData()).resolves.toMatchObject({data: {success: true}})
});
test('promise异步函数测试,并且返回404',()=>{//下面expect必须被执行1次测试才能通过expect.assertions(1);return fetchData().catch(err=>{expect(err.toString().indexOf('404')>-1).toBe(true)})
});
//============================
test('promise异步函数测试', async () => {await expect(fetchData()).resolves.toMatchObject({data: {success: true}})
});test('promise异步函数测试,并且返回404', async () => {await expect(fetchData()).rejects.toThrow();
});

钩子函数

  • beforeAll :所有测试用例运行前执行
  • afterAll :所有测试用例运行之后执行
  • beforeEach :每个测试用例运行前执行
  • afterEach :每个测试用例运行之后执行

分组(钩子函数从外往内执行)

describe('分组测试', () => {beforeAll(() => {console.log('beforeAll')});afterAll(() => {console.log('AfterAll')});beforeEach(() => {console.log('beforeEach')});afterEach(() => {console.log('afterEach')});test('promise异步函数测试', async () => {await expect(fetchData()).resolves.toMatchObject({data: {success: true}})});
});

mock

1、捕获函数的调用和返回结果,以及this和调用顺序
2、自由设置函数返回结果
3、改变函数内部的实现

// mock.js
export function runCallback(fn) {fn('abc')
}
export function getData() {return axios.get('/api').then(res=>res.data);
}// mock.test.js
import {runCallback,getData} from "./fetch";// 1、捕获函数的调用和返回结果,以及this和调用顺序
// 2、自由设置函数返回结果
test('测试 runCallback',()=>{// 以下三种方式都是一样,设置函数返回结果// const fn = jest.fn(()=>{//     return 'hello'// });// fn.mockImplementation(()=>'hello');// fn.mockReturnValueOnce(()=>'hello');// fn.mockReturnValueOnce('hello'); // 返回值只返回一次,也就是第一次执行的时候有返回值,后面的没有const fn = jest.fn(); // mock函数,1、捕获函数的调用和返回结果,以及this和调用顺序fn.mockReturnValue('hello'); // 自由设置函数返回结果runCallback(fn);runCallback(fn);expect(fn.mock.calls.length).toBe(2);expect(fn.mock.results[0].value).toBe('hello');expect(fn).toBeCalled();expect(fn).toBeCalledWith('abc'); // 函数每次被调用的时候都传入abc这个参数console.log(fn.mock);// {//     calls: [ ['abc'], ['abc'] ],  //函数被调用次数,以及每次被调用时的参数//     instances: [ undefined, undefined ],  // 函数this指向//     invocationCallOrder: [ 1, 2 ],//     results: [ //每次执行的返回值//     { type: 'return', value: 'hello' },//     { type: 'return', value: 'hello' }// ]// }
});// ====================
// 3、改变函数内部的实现
import axios from 'axios';
jest.mock('axios');
test.only('测试 改变函数内部的实现',async ()=>{axios.get.mockResolvedValue({data:'hello'});await getData().then(res=>{expect(res).toBe('hello')})
});

mock进阶

// fetch.js
import axios from 'axios';
export function getData() {return axios.get('/').then(res=>res.data)
}
export function getNumber() {return 123
}// __mocks__/fetch.js
export function getData() {return Promise.resolve("(function a(){return 123})()")
}// fetch.test.js
/*** 方法一:* 1、在项目根目录新建__mocks__文件夹* 2、在__mocks__文件夹下面新建一个跟需要mock的文件同名的文件,并重写需要进行测试的方法* 3、jest在测试的时候会去寻找__mocks__下面的fetch.js,而不是真实引入的fetch.js** 方法二:* 在jest.config.js文件中开启 automock: true*/
jest.mock('./fetch');
import {getData} from "./fetch";
// getNumber这个函数不需要mock
const {getNumber} = jest.requireActual('./fetch.js');
test('getData',()=>{return  getData().then(data=>{expect(eval(data)).toEqual(123)})
});
test('getNumber',()=>{expect(getNumber()).toEqual(123)
});

snapshot 快照测试

  • 一般用于测试配置文件
  • 第一次测试的时候没有快照文件会先生成快照文件,第二次测试会用新生成的快照文件与旧的快照文件对比
  • u模式可以更新全部快照文件
  • i模式会逐个快照进行询问是否需要更新
// snapshot.js
export function getConfing() {return {name:'张三',age:12,sex:'nan1'}
}
export function getOtherConfing() {return {name:'张三',age:12,sex:'nan1',time:new Date()}
}// snapshot.test.js
import { getConfing, getOtherConfing } from "./fetch";
test("测试快照,toMatchSnapshot", () => {expect(getConfing()).toMatchSnapshot();
});
test("测试快照,toMatchSnapshot", () => {// toMatchInlineSnapshot(必须安装prettier) 把快照内容放到测试文件中,而不是生成快照文件expect(getOtherConfing()).toMatchInlineSnapshot({time: expect.any(Date), //  指定time为Date类型,不然每次生成的Date实例都不一样,导致测试不通过},`Object {"age": 12,"name": "张三","sex": "nan1","time": Any<Date>,}`);
});

mock – timers定时器

// timer.js
export function timer(fn) {setTimeout(fn,3000)
}
export function timer1(fn) {setTimeout(()=>{fn();setTimeout(fn,3000)},3000)
}// timer.test.js
import {timer,timer1} from "./fetch";
// mock定时器
jest.useFakeTimers(); // 最好在beforeEach钩子函数中调用,不然可能会导致在测试用例中相互影响
test('timer--runAllTimers',()=>{const fn = jest.fn();timer(fn);jest.runAllTimers();// 期望函数被执行一次expect(fn).toHaveBeenCalledTimes(1);
});
test('timer1--runOnlyPendingTimers',()=>{const fn = jest.fn();timer1(fn);// 只执行处于队列中的定时器jest.runOnlyPendingTimers();expect(fn).toHaveBeenCalledTimes(1);jest.runOnlyPendingTimers();expect(fn).toHaveBeenCalledTimes(2);
});
test('timer1--advanceTimersByTime',()=>{const fn = jest.fn();timer1(fn);// 将定时器时间快进6秒jest.advanceTimersByTime(6000);expect(fn).toHaveBeenCalledTimes(2);
});

ES6 中类的测试

// Util.js
class Util {a(){}b(){}
}
export default Util;// demoUtil.js
import Util from "./util";
export function demoUtil() {const util = new Util();util.a();util.b();
}// demoUtil.test.js// 集成测试:把单元测试中的其他东西也进行测试了
// jest发现util导出的是一个类,会自动进行mock(或者可以手动mock)
// Util=jest.fn(),Util.prototype.a=jest.fn(),Util.prototype.b=jest.fn()
jest.mock('./util');
import {demoUtil} from './fetch';
import Util from './util'
test('测试',()=>{demoUtil();// Util是单元测试中的其他东西expect(Util).toHaveBeenCalled();expect(Util.mock.instances[0].a).toHaveBeenCalled();expect(Util.mock.instances[0].b).toHaveBeenCalled();
});

总结

其实前端测试还是比较简单的,难点主要是在于测试用例的编写,你要去考虑不同的情况产生的效果。学完这个jest测试框架,我觉得自己最大的收获并不是学会了这个测试框架怎么使用,而是思维和思考上的收获,因为在编写测试用例的时候我需要思考每个数据传入空会产生什么效果,传入null或者undefined又会产生什么效果,我需要考虑到的边界情况非常多,通过思考这些问题,我在编写代码的时候就需要判断这些边界情况,从而提高代码质量。好了,这篇文章就写到这里吧,下一阶段的学习目标就是持续集成和持续部署(简称CICD)

前端测试框架—jest基本使用相关推荐

  1. 前端测试框架Jest系列教程 -- Expect(验证)

    写在前面 在编写测试时,我们通常需要检查值是否满足某些条件,Jest中提供的expect允许你访问很多"Matchers",这些"匹配器"允许您验证不同的东西. ...

  2. 前端测试框架Jest——语法篇

    使用匹配器 使用不同匹配器可以测试输入输出的值是否符合预期.下面介绍一些常见的匹配器. 普通匹配器 最简单的测试值的方法就是看是否精确匹配.首先是toBe() test('two plus two i ...

  3. 前端自动化测试框架 Jest 极简教程

    前端自动化测试框架 Jest 极简教程 Delightful JavaScript Testing. https://jestjs.io Jest是由Facebook发布的开源的.基于Jasmine的 ...

  4. 前端自动化测试框架Jest介绍和使用

    在实际项目的自动化测试过程中,如果只有这两个方法,很显然,是远远不够的,这时候,就需要我们对之前的方法进行扩充,同时还有很多自动化的机制需要集成进去.这时候 Jest 闪亮登场! Jest 框架介绍 ...

  5. 测试框架 Jest 实例教程

    Jest 是由 Facebook 开源出来的一个测试框架,它集成了断言库.mock.快照测试.覆盖率报告等功能.它非常适合用来测试 React 代码,但不仅仅如此,所有的 js 代码都可以使用 Jes ...

  6. 顶级测试框架Jest指南:跑通一个完美的程序,就是教出一群像样的学生

    facebook三大项目:yarn jest metro,有横扫宇宙之势. 而jest项目的宗旨为:减少测试一个项目所花费的时间成本和认知成本. --其实,它在让你当一个好老师. jest文档非常简略 ...

  7. 前端测试框架(学习之路)前言

    为什么需要单元测试 正确性:测试可以验证代码的正确性,在上线前做到心里有底 自动化:当然手工也可以测试,通过console可以打印出内部信息,但是这是一次性的事情,下次测试还需要从头来过,效率不能得到 ...

  8. 前端自动化测试框架Jest中的Mock

    众所周知,在前面的代码中,我们在编写一个测试用例的时候用到了 test.expect.toBe 三个方法,在之前我们也介绍了 Jest 的基础使用.Jest 的简单配置. Jest 中的匹配器(mat ...

  9. mocha检测c语言,前端测试框架mocha使用小结

    安装 npm i -g mocha npm i chai -D //断言库 模块测试 比如有一个add函数 //add.js function add(a, b){ return a + b } mo ...

最新文章

  1. Levenshtein distance 编辑距离算法
  2. 尝试在wireshark中查找密码
  3. 左右躲避障碍-神手ts版本
  4. 不带头结点的单链表------C语言实现
  5. [leetcode] 68.二叉树的最近公共祖先
  6. 前端学习(1833):前端面试题之nodejs的轮询机制
  7. C++STL与泛型编程__侯捷视频_学习博客_总目录
  8. 查询mysql数据库中所有表名
  9. jquery 操作 input显示或者隐藏
  10. linux日期函数使用技巧[转自那天的blog]
  11. Redis入门指南(三)
  12. 一个四维混沌吸引子曲线(matlab完整代码)
  13. Qt编写1024游戏
  14. CuInS2/ZnS-PEG量子点|1I-V族三元化合物铜钢硫(CuInS2简称CIS),CuInS2/ZnS核壳量子点
  15. SLAM高翔视频第二讲萝卜习题
  16. 如何提高内存卡的读写速度
  17. 为地震死去的孩子们而作(转载)
  18. 如何在模拟器中安装App
  19. apt install 提示无法解析域名“cn.archive.ubuntu.com”
  20. json spr路驾驶技术视频api_TED视频下载及API接口

热门文章

  1. 基于Matlab的压力控制论文,基于Matlab \ Simulink的气体辅助注射压力控制系统的建模与仿真...
  2. 虚拟机VS容器 安全比拼谁更胜一筹?
  3. 0x00007FF7C49A4C42 处有未经处理的异常:0xC0000005: 读取位置 0x000001481A2D86C4 时发生访问冲突
  4. python解越南逆天小学数学题
  5. 使用图像播放Java中的一种技巧-搜索图像,将图像转换为文本,隐藏数据
  6. 2004.8.18日--全国3D第一期
  7. VScode中无法使用转到定义
  8. 攻防世界-leaking-(详细操作)做题过程
  9. 攻防世界xctfweb题leaking题解
  10. uni-app页面跳转以及传值