记一次基于 Jest 的测试驱动开发

jest 官方文档:https://www.jestjs.cn/

最近因为一个需求逻辑较为复杂,所以干脆采用了 TDD(测试驱动开发) 的方法,先写好函数参数和返回值类型,然后写完测试用例,最后再实现函数,通过所有测试即为逻辑正确。

开始

首先,既然要使用 jest ,那么肯定要先安装。

npm i -D jest

然后进行配置,最简单的方式是在 package.json 文件中添加一个 jest 配置

{
  "jest": {
    "moduleNameMapper": {
      "^@/(.*)$": "<rootDir>/$1"
    },
    "moduleFileExtensions": [
      "js",
      "json",
      "ts"
    ],
    "rootDir": "src",
    "testRegex": ".test.ts$",
    "transform": {
      "^.+\\.(t|j)s$": "ts-jest"
    },
    "testEnvironment": "node"
  }
}

由于本项目用到了 TypeScript ,所以还需要额外安装 ts-jest,其他的看自己项目配置即可。

编写函数参数和返回值类型

// sum.ts
export function sum(a:number, b:number):number { 
    // 此时没有任何实现,ts 肯定会报错,空着就行,也可以随便返回一个值
  return 0
}

编写测试用例

例如

// sum.test.ts
import { sum } from './sum'

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3)
})
test('adds 1 + 1 to equal 2', () => {
  expect(sum(1, 1)).toBe(2)
})
test('adds 0 + 0 to equal 0', () => {
  expect(sum(0, 0)).toBe(0)
})

运行测试-失败

将如下代码添加到 package.json 中:

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

最后,运行 npm test

FAIL  src/utils/sum.test.ts
  ● 测试 sum › adds 1 + 2 to equal 3
                                                                                                                                                                             
    expect(received).toBe(expected) // Object.is equality                                                                                                                                                                      
    Expected: 3                                                                                                                                                              
    Received: 0                                                                                                                                                              
                                                                                                                                                                             
       6 | describe('测试 sum', () => {                                                                                                                                      
       7 |     test('adds 1 + 2 to equal 3', () => {
    >  8 |         expect(sum(1, 2)).toBe(3)
         |                           ^
       9 |     })
      10 |     test('adds 1 + 1 to equal 2', () => {
      11 |         expect(sum(1, 1)).toBe(2)

      at Object.<anonymous> (utils/sum.test.ts:8:27)

  ● 测试 sum › adds 1 + 1 to equal 2

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

    Expected: 2
    Received: 0

       9 |     })
      10 |     test('adds 1 + 1 to equal 2', () => {
    > 11 |         expect(sum(1, 1)).toBe(2)
         |                           ^
      12 |     })
      13 |     test('adds 0 + 0 to equal 0', () => {
      14 |         expect(sum(0, 0)).toBe(0)

      at Object.<anonymous> (utils/sum.test.ts:11:27)

由于此时函数还没有实现,所以不出意外的执行失败了,不过没关系,接下来实现函数即可

实现函数

接下来实现函数

// sum.ts
export function sum(a:number, b:number):number { 
  return a+b
}

再次运行测试-成功

运行 npm test ,此时应该会看到 3 个用例都通过测试了

 PASS  src/utils/sum.test.ts
  测试 sum
    √ adds 1 + 2 to equal 3 (1 ms)                                                                                                                                           
    √ adds 1 + 1 to equal 2                                                                                                                                                  
    √ adds 0 + 0 to equal 0                                                                                                                                                                                                                                             
Test Suites: 1 passed, 1 total                                                                                                                                               
Tests:       3 passed, 3 total                                                                                                                                               
Snapshots:   0 total
Time:        4.133 s, estimated 5 s
Ran all test suites.

总结

测试驱动开发的内涵就是先写测试用例,然后再具体实现。

虽然本文中的例子是个非常简单的加法函数,但笔者具体实现的那个函数却还是有些复杂,逻辑上也是捋了半天才搞明白。

笔者一开始编写了十个测试用例,当经过反复修改终于全部通过的时候,那种发自内心的喜悦还是非常令人激动的,可以说是攻克了一大难题。

这次开发的经验教训也使我明白,有时候,还是要写点测试用例为好,免得哪里出错了都不知道~