[路飞]_前端测试框架 Jest 初探

246 阅读3分钟

「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战

什么是 Jest

Jest 是一个令人愉快的 JavaScript 测试框架,专注于简洁明快。

这些项目都在使用 Jest:Babel、 TypeScript、 Node、 React、 Angular、 Vue 等等!

安装

使用 npm 安装

npm install --save-dev jest

使用

1. 在 webpack 中使用

package.json 文件中增加以下配置项

"scripts": {
    "test": "jest"
}

2. 添加测试的目标代码

我们前面做了力扣的算法题 227. 基本计算器 II,现在给这个算法增加一个单元测试。

文件名 46.w0501-calculate.js,代码如下:

function calculate(s) {
  s = s.trim()
  const len = s.length
  const stack = []
  let num = 0 //存当前数字
  let preSign = '' //把前一个操作记下来

  for (let i = 0; i < len; i++) {
    if (s[i] === ' ') continue

    let tmp = Number(s[i])
    //拼接相邻数组
    if (!isNaN(tmp)) {
      num = num * 10 + tmp
    }

    if (isNaN(tmp) || i === len - 1) {
      switch (preSign) {
        case '':
        case '+':
          stack.push(num)
          break
        case '-':
          stack.push(-num) //减法转化成加法
          break
        case '*':
          stack.push(stack.pop() * num)
          break
        case '/':
          stack.push(stack.pop() / num | 0)
          break
      }

      preSign = s[i] //记下前一个操作符
      num = 0
    }
  }

  //返回栈内所有元素之和
  return stack.reduce((prev, curr) => prev + curr)
}

module.exports = calculate

3. 创建测试用例

接下来创建 calculate.test.js 文件,jest 会在当前工程下找以 test.js 为扩展名的文件,从文件中获取测试用例执行,我们写一个简单的测试用例,代码如下:

//导入要做单元测试的函数
const calculate = require('../algorithm/46.w0501-calculate')

test('1+1=2', () => {
  expect(calculate('1+1')).toBe(2)
})

4. 执行测试命令

npm run test
测试通过

如果顺利的话,我们会看到如下结果

> test
> jest

 PASS  __tests__/calculate.test.js
   1+1=2 (2 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.119 s
Ran all test suites.
测试不通过

如果测试不通过会是这样

> test
> jest

 FAIL  __tests__/calculate.test.js1+1=2 (2 ms)
  ✕ calculate(' 10 + 10 / 2 - 5 * 9 ') (3 ms)

  ● calculate(' 10 + 10 / 2 - 5 * 9 ')

    expect(received).toBe(expected) // Object.is equality

    Expected: -30
    Received: 10

       7 |
       8 | test(`calculate(' 10 + 10 / 2 - 5 * 9 ')`, () => {
    >  9 |   expect(calculate(' 10 + 10 / 2 - 5 * 9 ')).toBe(-30)
         |                                              ^
      10 | })

      at Object.<anonymous> (__tests__/calculate.test.js:9:46)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 passed, 2 total
Snapshots:   0 total
Time:        0.976 s, estimated 1 s
Ran all test suites.

以下打印结果表示

1+1=2 (2 ms) 
✕ calculate(' 10 + 10 / 2 - 5 * 9 ') (3 ms)
  • 名为 1+1=2 的用例通过
  • 名为 calculate(' 10 + 10 / 2 - 5 * 9 ') 的用例没通过

以下打印结果表示

    Expected: -30
    Received: 10

       7 |
       8 | test(`calculate(' 10 + 10 / 2 - 5 * 9 ')`, () => {
    >  9 |   expect(calculate(' 10 + 10 / 2 - 5 * 9 ')).toBe(-30)
         |                                              ^
      10 | })
  • calculate(' 10 + 10 / 2 - 5 * 9 ') 预期是 -30(Expected: -30) 但是实际执行返回了 10(Received: 10),所以用例没通过,并且指出没通过的用例在第 9 行。

常用 API

describe

相当于对测试用例分组

describe('outer', () => {
    console.log('describe outer-a');
    
    describe('describe inner 1', () => {
        console.log('describe inner 1');
        test('test 1', () => {
            console.log('test for describe inner 1');
            expect(true).toEqual(true);
        });
    });

    console.log('describe outer-b');
    
    test('test 1', () => {
        console.log('test for describe outer');
        expect(true).toEqual(true);
    });
});
test

test(arg1, arg2) 包含两个参数,第一个参数这个测试的描述信息,方便我们查看用例执行结果。第二个参数是这个测试要执行的逻辑,包括了普通代码和匹配器。

expect

expect(arg1).toBe(x) 是匹配器,我们测试一个函数时,通过匹配器对比函数的返回结果和预期结果,如果两者一致则当前匹配器通过。expect(calculate('1+1')).toBe(2) 表示执行calculate('1+1')的结果和2匹配要相等这个用例才通过。

toBe 使用的是绝对相等,如果是对象比较需要使用 toEqual。

test('object assignment', () => {
  const data = {one: 1};
  data['two'] = 2;
  expect(data).toEqual({one: 1, two: 2});
});

常用的匹配器:

  • toBe 绝对等于
  • toEqual 是否等于

真假类的匹配器:

  • toBeNull 匹配 null
  • toBeUndefined 匹配 undefined
  • toBeDefined 匹配定义过的变量
  • toBeTruthy 匹配 true
  • toBeFalsy 匹配 false
  • toBeGreaterThan

数组类匹配器:

  • toBeGreaterThan 大于
  • toBeGreaterThanOrEqual 大于等于
  • toBeLessThan 小于
  • toBeLessThanOrEqual 小于等于

字符串类匹配器

  • expect('team').not.toMatch(/I/) 是否不匹配正则
  • expect('Christoph').toMatch(/stop/) 是否匹配正则

数组类型匹配器

  • toContain 是否包含

更多匹配器见官网 匹配器

详细使用说明请看官方文档:www.jestjs.cn/docs/gettin…