Jest 运行 TypeScript 单测并增加覆盖率

5,007 阅读2分钟

建议废弃 Jest 使用 Vitest 2023-11-23

本文将介绍如何用 jest 跑 ts 单测,无需编译,且增加单测覆盖率以避免代码少测或年久失修腐化问题。如果遇到问题可参考 Jest test ESM

开始配置

可以 cli 一键配置或不放心可以选择下面的手动配置模式

CLI 一键配置 推荐

TS

$ npx create-test-app --type ts
# 或
$ pnpx create-test-app --type ts

JS

$ npx create-test-app --type js

注意将自动设置覆盖率 100%,可通过增加参数 --coverage=80 自定义

手动配置

推荐使用 CLI 一键配置

安装依赖

npm i -D jest typescript ts-jest @types/jest

生成 jest.config.js

npx ts-jest config:init

运行单测

npm test

单测示例

单测书写规范来自小程序最佳实践之『单测』篇 👮

// lite-lodash.test.ts
import { isPromise } from '../src/lib/lite-lodash'

describe('isPromise', () => {
  it('`Promise.resolve()` should be a promise', () => {
    const input = Promise.resolve();
    const actual = isPromise(input);
    const expected = true;

    expect(actual).toEqual(expected);
  });

  it('`number` should not be a promise', () => {
    const input = 100;
    const actual = isPromise(input);
    const expected = false;

    expect(actual).toEqual(expected);
  });
});

运行结果:

    isPromise
      ✓ should Promise.resolve be a promise
      ✓ should new Promise be a promise (1 ms)

覆盖率报告和阈值设置

通过阈值设置保证代码质量不会随着迭代劣化。

执行命令前务必保证之前的代码已经 commit。因为将会覆盖配置文件,或直接跳转到下面 jest.config.js 章节。

设置覆盖率

npx jest --init

✔ It seems that you already have a jest configuration, do you want to override it? … yes

The following questions will help Jest to create a suitable configuration for your project

✔ Would you like to use Typescript for the configuration file? … no

✔ Choose the test environment that will be used for testing › node

✔ Do you want Jest to add coverage reports? … yes

✔ Which provider should be used to instrument code for coverage? › v8

✔ Automatically clear mock calls and instances between every test? … no

📝 Configuration file created at jest.config.js

jest.config.js

module.exports = {
   preset: 'ts-jest',
   testEnvironment: "node",

+  coverageDirectory: "coverage",
+  coverageProvider: "v8",
+  coverageThreshold: {
    "global": {
      "branches": 100,
      "functions": 100,
      "lines": 100,
      "statements": 100
    }
  },
}

package.json

   "scripts": {
     "build": "tsc --declaration",
     "preversion": "npm run build",
-    "test": "jest"
+    "test": "jest --coverage"
   },

.gitignore

覆盖率报告无需保存到代码库。至于覆盖率报告如何阅读,见写一篇。

+coverage/

生成覆盖率报告

npm test

----------------|---------|----------|---------|---------|-------------------
File            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------------|---------|----------|---------|---------|-------------------
All files       |     100 |      100 |     100 |     100 |
 lite-lodash.ts |     100 |      100 |     100 |     100 |
----------------|---------|----------|---------|---------|-------------------

故意少测试函数,看看失败效果

----------------|---------|----------|---------|---------|-------------------
File            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------------|---------|----------|---------|---------|-------------------
All files       |   72.73 |      100 |   66.67 |   72.73 |
 lite-lodash.ts |   72.73 |      100 |   66.67 |   72.73 | 5-7
----------------|---------|----------|---------|---------|-------------------
Jest: "global" coverage threshold for statements (100%) not met: 72.73%
Jest: "global" coverage threshold for lines (100%) not met: 72.73%
Jest: "global" coverage threshold for functions (100%) not met: 66.67%

npm ERR! code 1

单测失败 exit code 不等于 0,导致 ci 失败。达到了用覆盖率阻止代码少测或劣化问题 👍。

参考

TODO