使用 jest 来测试 TypeScript 代码(单测、覆盖率)

jest 的使用直接看文档就可以了,本文不会描述 jest 的具体使用流程,主要是一些使用 case。

需要 jest 26 以上版本

使用 ts 来写 jest config

jest 默认是支持直接使用 ts 来写 config, 可以从 @jest/types 中获取得到配置类型定义。

1
2
3
4
5
6
import type {Config} from '@jest/types';

const config: Config.InitialOptions = {
};

export default config;

直接测试 ts 代码

直接测试 ts 代码需要使用 ts-jest,并进行相应的配置:

1
2
3
4
5
6
7
import type {Config} from '@jest/types';

const config: Config.InitialOptions = {
preset: 'ts-jest'
};

export default config;

配置上 ts-jest 就可以直接使用 ts 来写 xxx.test.ts 这样的测试文件了,也可以测试 ts 代码。

生成覆盖率

生成覆盖率需要设置 collectCoverage 选项:

1
2
3
4
5
6
7
8
9
import type {Config} from '@jest/types';


const config: Config.InitialOptions = {
preset: 'ts-jest',
collectCoverage: true
};

export default config;

rootDir 选项

rootDir 选项感觉没有设计好。这个选项设置的并不是测试文件所在的根目录,而是所有代码的根目录。

01.png

假如我们有这样一个目录结构,src 目录是源代码,test 目录时测试代码,script 目录是一些脚本文件。

如果我们将 rootDir 设置为 .,那么 script 目录下如果有 test.js,也会被识别为测试文件。

如果我们将 rootDir 设置为 test,可以解决上述问题,但是会发现生成的覆盖率里文件是空的,没有扫描到 src 目录下。

我现在就将 rootDir 设置为 .,然后尽量避免其他文件夹下有 xxx.test.js 形式命名的代码。

忽略掉 .d.ts

可以指定哪些文件算在覆盖率测试中,通常我们需要忽略掉 .d.ts 文件。

1
2
3
4
5
6
7
8
9
import type {Config} from '@jest/types';

const config: Config.InitialOptions = {
collectCoverageFrom: [
'src/**/!(*.d).{js,ts}',
]
};

export default config;

测试 webpack loader 和 plugin

如果我们写了一个 loader 或者 plugin 要测试,需要整体跑 webpack,不能只对这个 loader 或者 plugin 来进行测试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import path from 'path';
import webpack from 'webpack';
import {createFsFromVolume, Volume} from 'memfs';
import {getConfig} from './webpack.config';

export function compiler(fixture: string): Promise<webpack.Stats> {
const config = getConfig(fixture);
const compiler = webpack(config);

// @ts-ignore
compiler.outputFileSystem = createFsFromVolume(new Volume());
compiler.outputFileSystem.join = path.join.bind(path);

return new Promise((resolve, reject) => {
compiler.run((err, stats) => {
if (err) {
reject(err);
}
if (stats.hasErrors()) {
reject(new Error(stats.toJson().errors.join('\n')));
}

resolve(stats);
});
});
};

使用 memfs 可以防止向硬盘中写文件内容,输出文件会存在内存中,可以在测试用使用。

可以使用 stats.toJson().modules[0].source 来得到输出内容。