梅旭光的个人博客

装X是写博客的第一源动力🐶

0%

使用 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 选项感觉没有设计好。这个选项设置的并不是测试文件所在的根目录,而是所有代码的根目录。

/images/2020/jest-typescript/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
10
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 来得到输出内容。