Open taoliujun opened 10 months ago
Jest snapshot是把双刃剑,虽然使用它可以快速的编写测试用例,但也导致开发者忽略了测试用例的细节设计。
试想一个场景,有一个方法返回了复杂的结构,开发者A由于懒惰或自信以后能根据snapshot的结果来修复问题,而只写了snapshot。过了一段时间,开发者A或B修改了该方法,发现snapshot匹配失败,那么他会这样做:
我相信,大部分人都会选择第二种方式,因为这样更快,更简单。但后果是,大家都只关心了方法的结果,而忽略了方法的细节设计,这样的测试用例是不可靠的。即便在pull request环节,Reviewers面对难以阅读的snapshot文件,也往往是选择了approve。
所以,需要一个方案来实现几个目的:
因为jest的限制,执行用例肯定会影响覆盖率。那么可以执行两次用例,一次是执行包含snapshot的文件来校验用例,一次是执行不包含snapshot的文件来生成测试覆盖率。
于是,新增两个script:
script
// package.json "scripts": { "test": "pnpm exec jest", "test:coverage": "pnpm exec jest --config=jest.coverage.config.js", },
默认的jest.config.js配置不包含覆盖率配置,而jest.coverage.config.js包含覆盖率配置。
jest.config.js
jest.coverage.config.js
// jest.config.js module.exports = { // ... };
// jest.coverage.config.js const baseConfig = require('./jest.config'); module.exports = { ...baseConfig, testMatch: ['**/src/**/__tests__/**/*.ts', '!**/src/**/__tests__/**/*.snap.test.ts'], collectCoverage: true, collectCoverageFrom: ['src/**/*.ts', '!src/**/*.snap.test.ts', '!src/index.ts'], coverageDirectory: 'reports/jest', coverageThreshold: { global: { lines: 90, branches: 50 } }, coverageReporters: ['html'], };
在jest.coverage.config.js中,testMatch排除执行.snap.test.ts用例文件,collectCoverageFrom也排除了.snap.test.ts文件本身作为源码文件被收集的问题。
testMatch
.snap.test.ts
collectCoverageFrom
接下来,只需要把包含toMatchSnapshot等方法的测试用例,单独成文件且命名为*.snap.test.ts,就可以了。
toMatchSnapshot
*.snap.test.ts
Jest snapshot是把双刃剑,虽然使用它可以快速的编写测试用例,但也导致开发者忽略了测试用例的细节设计。
问题
试想一个场景,有一个方法返回了复杂的结构,开发者A由于懒惰或自信以后能根据snapshot的结果来修复问题,而只写了snapshot。过了一段时间,开发者A或B修改了该方法,发现snapshot匹配失败,那么他会这样做:
我相信,大部分人都会选择第二种方式,因为这样更快,更简单。但后果是,大家都只关心了方法的结果,而忽略了方法的细节设计,这样的测试用例是不可靠的。即便在pull request环节,Reviewers面对难以阅读的snapshot文件,也往往是选择了approve。
所以,需要一个方案来实现几个目的:
方案
因为jest的限制,执行用例肯定会影响覆盖率。那么可以执行两次用例,一次是执行包含snapshot的文件来校验用例,一次是执行不包含snapshot的文件来生成测试覆盖率。
于是,新增两个
script
:默认的
jest.config.js
配置不包含覆盖率配置,而jest.coverage.config.js
包含覆盖率配置。在
jest.coverage.config.js
中,testMatch
排除执行.snap.test.ts
用例文件,collectCoverageFrom
也排除了.snap.test.ts
文件本身作为源码文件被收集的问题。接下来,只需要把包含
toMatchSnapshot
等方法的测试用例,单独成文件且命名为*.snap.test.ts
,就可以了。