使用jest测试用例之入门篇

Jest使用

Jest 是由 Facebook 开发的一个 js 测试框架,jest 主要侧重于被用于做单元测试和集成测试

安装

js 复制代码
npm i jest -D

运行

**package.json**里面配置命令

js 复制代码
// scripts添加测试脚本
{
    "test": "jest" /* 运行后便会使用 jest 执行所有的 .test.js 为后缀的测试文件 */
}
// 如果只想测试对应的文件并一直执行,可以使用如下命令
{
    "test": "npx jest 测试文件名称 --watch"
}

运行相应的文件代码,√ 测试加法 (5 ms)是测试通过,代表写的程序没问题, × 测试加法 (8 ms)是没通过

需要的结果-Expected: 3

实际的结果-Received: 4

使用

在项目中的任意位置(通常单独建个名为 test 的文件夹)新建以 .test.js 为后缀的测试文件,如 expect.test.js (若项目中有 test.js 存在,请改为其他名称,JEST 会将 test.js 也视为测试文件)

安装了 jest 之后,会提供一些全局的方法或者对象,例如 ++test、expect、jest++,这些方法或者对象不需要导入,直接在测试文件中使用即可

it 方法实际上是 test 方法的一个别名

**expect**是断言方法

分组

describe

可以针对不同的测试用例来进行分组,分组语法:++describe++(这个分组的描述,回调函数),该方法也是一个全局方法,不需要导入直接使用

js 复制代码
const { sum, sub, mul, div } = require('./tools')
describe("这是一组测试,测试加减法", () => {
  // 回调函数中就放一个一个的测试用例

  /**
   * 一个 test 方法意味着书写了一个测试用例
   * param1 :针对这个测试用例的一个描述
   * param2 :执行该用例所对应的回调函数
   */
  test("测试加法", () => {
    expect(sum(1, 2)).toBe(3);
  });

  test("测试减法", () => {
    expect(sub(10, 5)).toBe(5);
  });
});

describe("这是一组测试,测试乘除法", () => {
  /**
   * it 方法实际上是 test 方法的一个别名
   */
  it("测试乘法", () => {
    expect(mul(2, 3)).toBe(6);
  });

  it("测试除法", () => {
    expect(div(10, 2)).toBe(5);
  });
});

修饰符

not

用于对断言进行取反操作,可以与各种断言函数结合使用,以表示一个断言的否定形式。

js 复制代码
// not表示不相等
it('1+2不等于4', () => {
    // 1+2判断不等于4
    expect(1+2).not.toBe(4) //  true
})
resolves
rejects

匹配器

toBe

执行的是 ES6 的Object.is,与严格相等运算符(===)基本一致,不会进行强制类型转换,不同之处为 +0不等于-0,NaN等于自身,对引用类型的数据(如对象、数组等),比较其地址是否相同。

js 复制代码
const { sum, sub, mul, div } = require("./tools")
test("断言2+2=4", () => {
  expect(2 + 2).toBe(4);
});

// 可以以相同的方式测试其他的工具函数:
it("测试加法", ()=>{
  expect(sum(1, 2)).toBe(3);
  expect(sub(10, 5)).toBe(5);
  expect(mul(2, 3)).toBe(6);
  expect(div(10, 2)).toBe(5);
})
// toBe比较不了深度对象
test('深度比较对象', () => {
  const stu = {name : "张三", score : {html : 100, css : 90}};
  expect(stu).not.toBe({name : "张三", score : {html : 100, css : 90}}) // 测试通过
})
toEqual

会递归比较对象的所有属性, 比较数组/对象的每一项,但会忽略 undefined

js 复制代码
test('深度比较对象', () => {
  // expect({ a: 1, b: 2 }).toEqual({ a: 1, b: 2 }) // 结果是true
  const stu = {name : "张三", score : {html : 100, css : 90}};
  expect(stu).toEqual({name : "张三", score : {html : 100, css : 90}}) // 测试通过
  expect(stu).toEqual({name : "张三", score : {html : 100, css : 100}}) // 测试报错
})

it('有undefined', () => {
  const stu = {name : "张三", job: undefined, score : {html : 100, css : 90}};
  expect(stu).toEqual({name : "张三", score : {html : 100, css : 90}}) // 测试通过
})

**++toBe与toEqual++**的区别是:

toBe ‌用于比较两个值是否严格相等(使用===操作符)适用于以下场景:

  • ‌原始类型‌:如数字、字符串、布尔值。
  • ‌引用类型‌:检查两个引用是否指向同一个内存地址。

toEqual‌用于深度比较两个对象或数组,检查它们的值是否相等,而不是检查它们是否指向同一个内存地址。它适用于以下场景:

  • ‌对象‌:比较对象的属性值是否相等。
  • ‌数组‌:比较数组的元素是否相等
toStrictEqual

严格相等:与 toEqual 类似,但不会忽略 undefined

js 复制代码
it('有undefined', () => {
  const stu = {name : "张三", job: undefined, score : {html : 100, css : 90}};
  expect(stu).toStrictEqual({name : "张三", score : {html : 100, css : 90}}) // 测试报错
})
布尔值

toBeFalsy: 断言为 false

toBeTruthy:断言为 true

toBeNull: 断言为 null

toBeDefined:测试一个值是否被定义,即检查该值是否不是undefined

toBeUndefined:断言为 undefined

js 复制代码
test("布尔值相关匹配器",()=>{
  const n = null;
  expect(n).toBeFalsy();
  // 取反:是false
  expect(n).not.toBeTruthy();

  const a = 0;
  // 0是false
  expect(a).toBeFalsy();
  // toBeTruthy断言是true,not是取反就是false
  expect(a).not.toBeTruthy();
})

test("无参匹配器",()=>{
  const n = null;
  // toBeNull断言是null
  expect(n).toBeNull();
  // toBeDefined断言不是undefined
  expect(n).toBeDefined();
  // toBeUndefined断言不是undefined
  expect(n).not.toBeUndefined();
  const a = 0;
  // toBeNull断言不是null
  expect(a).not.toBeNull();
  // toBeDefined断言不是undefined
  expect(a).toBeDefined();
  // toBeUndefined断言不是undefined
  expect(a).not.toBeUndefined();
})
数值

数值就是两个数值之间大小的比较,有大于、大于等于、小于、小于等于之类的

toBeGreaterThan:大于

toBeGreaterThanOrEqual:大于等于

toBeLessThan:小于

toBeLessThanOrEqual: 小于等于

toBeCloseTo:是否接近某个数

js 复制代码
// 数值匹配器
test("数值相关匹配器",()=>{
  const a = 1;
  const b = 2;
  // toBeGreaterThan断言大于
  expect(a).toBeGreaterThan(b); // 输出错误
  // toBeGreaterThanOrEqual断言大于等于
  expect(a).toBeGreaterThanOrEqual(b); // 输出错误
  // toBeLessThan断言小于
  expect(a).toBeLessThan(b); // 输出正确
  // toBeLessThanOrEqual断言小于等于
  expect(a).toBeLessThanOrEqual(b);
  // 这里需要注意一下浮点数
  const value2 = 0.1 + 0.2;
  // toBeCloseTo断言是否接近
  expect(value2).toBeCloseTo(0.3);
  // toBeCloseTo 还接受第二个参数,第二个参数用于指定位数,默认是两位
  expect(0.302).toBeCloseTo(0.301);
  expect(0.302).not.toBeCloseTo(0.301, 5);
})
toMatch

可以检查字符串是否和某一个正则表达式能够匹配上

js 复制代码
test("字符串相关匹配器",()=>{
  expect("this is a test").toMatch(/test/); // 输出正确
  expect("this is a test").not.toMatch(/abc/); // 输出正确,not 取反
})
toContain

数组中查找指定项,toContain进行的是全等比较,也就是严格比较

js 复制代码
const shoppingList = [
  "diapers",
  "kleenex",
  "trash bags",
  "paper towels",
  "milk",
];
test("数组相关匹配器", () => {
  expect(shoppingList).toContain("milk");
  // toContain 进行的是全等比较,也就是严格比较
  expect([1, 2, 3]).not.toContain("1");
  expect([{ name: "张三" }, { name: "李四" }]).not.toContain({ name: "张三" });
  // // toContain 还可以用来检测一个字符串是否是另一个字符串的子串
  expect("this is a test").toContain("test");
  // // 也可以用到集合(set)里面
  expect(new Set(shoppingList)).toContain("milk");
});
toThrow

用于判断函数是否抛出异常,并可以指定抛出异常的具体内容。

js 复制代码
function compileCode(){
  throw new Error("aaa you are using the wrong JDK bbb");
}

test("异常相关的匹配器",()=>{
  expect(()=>compileCode()).toThrow();
  // toThrow 里面可以传递不同的参数
  expect(()=>compileCode()).toThrow(Error);
  expect(()=>compileCode()).toThrow("you are using the wrong JDK");
  expect(()=>compileCode()).toThrow(/JDK/);
})
arrayContaining

匹配一个测试返回的数组,它包含所有预期的元素。就是说,这个预期数组是测试返回数组的一个子集。

js 复制代码
const arr = ["张三"];
test("上面的数组不包含某一项", () => {
    expect(["李四", "王武", "赵六"]).toEqual(expect.not.arrayContaining(arr));
});
objectContaining

匹配一个测试返回的对象,它包含所有预期的元素。就是说,这个预期数组是测试返回对象的一个子集。

js 复制代码
const obj = {name : "张三"};
test("对象不包含上面的键值对",()=>{
  expect({age : 18}).toEqual(expect.not.objectContaining(obj));
  expect({name: "李四",age : 18}).toEqual(expect.not.objectContaining(obj));
})
相关推荐
用户7783366132113 分钟前
SerpBase驱动:用原生JS实现搜索意图分流浮层
前端
阿明的小蝴蝶3 分钟前
设备出厂横竖屏修改 & 默认手势导航修改(按键导航)
前端
SameX6 分钟前
ArkTS 做应用内"快捷胶囊" —— 续航日记踩过的两个鸿蒙声明式 UI workaround
前端
用户11481867894847 分钟前
水印的实现方式逻辑
前端·python
La Pulga10 分钟前
【FreeRTOS源码学习笔记】空闲任务与阻塞延时
笔记·mcu·学习·嵌入式·freertos·实时操作系统
蒸蒸yyyyzwd13 分钟前
秋招学习笔记 day106
笔记·学习
小李不想当小白1 小时前
WDG看门狗(STM32标准库学习笔记)
笔记·stm32·单片机·嵌入式硬件·学习·嵌入式
孟陬2 小时前
Foobar 技术周刊#160:大模型让大规模形式化软件验证成为现实丨AI写C++代码之后会发生什么?丨我们真的需要alpha() 函数吗丨重试,有时会让故障更
前端·后端·typescript
测试界的小码农2 小时前
【让 AI 生成的测试用例变成 pytest API 自动化脚本】
人工智能·测试用例·pytest
flash俊杰3 小时前
屏幕感知双通道:截图之外,为什么还要一份 UIA 控件清单
前端