结合现有项目,将使用到的前端框架(Vue、Angular、React)进行单元测试配置,整理配置文档
Vue
vue-cli在创建项目时可选择单元测试框架(Mocha 或 Jest),此处包含两种测试框架配置
Vue & Mocha
项目创建
项目创建时选择 Mocha 的Unit Testing
vue create vue-mocha
# 选择手动配置
? Please pick a preset:
zcloud (router, vuex, less, babel, eslint, unit-jest)
default (babel, eslint)
❯ Manually select features
? Please pick a preset: Manually select features
? Check the features needed for your project:
◉ Babel
◯ TypeScript
◯ Progressive Web App (PWA) Support
◉ Router
◉ Vuex
◉ CSS Pre-processors
◉ Linter / Formatter
◉ Unit Testing
❯◉ E2E Testing
# 单元测试 mocha + chai
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel, Router, Vuex, CSS Pre-processors, Linter, Unit, E2E
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with node-sass)
? Pick a linter / formatter config: Standard
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)Lint on save
? Pick a unit testing solution: (Use arrow keys)
❯ Mocha + Chai
Jest
添加测试报告mochawesome
现有架构测试报告都是在命令行展示,现在我们要将结果输出并展示在页面上
首先在项目中安装 mochawesome:
npm install --save-dev mochawesome
然后在 package.json 中修改 test:unit 命令如下:
"test:unit": "vue-cli-service test:unit --reporter=mochawesome"
添加测试覆盖率nyc
首先,在项目中安装所需依赖:
npm i --save-dev babel-plugin-istanbul istanbul-instrumenter-loader nyc
接着在项目根目录下新建 nyc.config.js 文件,其内容如下:
// 探索istanbul/nyc代码覆盖工具的原理 https://zhuanlan.zhihu.com/p/88524418
module.exports = {
'check-coverage': true,
'per-file': true,
'lines': 0,
'statements': 0,
'functions': 0,
'branches': 0,
'include': [
'src/**/*.js',
'src/**/*.vue'
],
'exclude': [
'src/abandon-ui/**',
'src/*.js',
'**/*.spec.js'
],
'reporter': [
'lcov',
'text',
'text-summary'
],
'extension': [
'.js',
'.vue'
],
'cache': true,
'all': true
}
完成后,在项目根目录新建 vue.config.js, 其内容如下:
const path = require('path')
const testMode = process.env.NODE_ENV === 'test'
module.exports = {
lintOnSave: false,
productionSourceMap: false,
chainWebpack: config => {
if (testMode) {
config.merge({
devtool: 'eval'
})
config.module
.rule('istanbul')
.test(/\.(js|vue)$/)
.include
.add(path.resolve(__dirname, '/src'))
.end()
.use('istanbul-instrumenter-loader')
.loader('istanbul-instrumenter-loader')
.options({ esModules: true })
.before('babel-loader')
}
}
}
完成后,打开项目根目录下的 babel.config.js 文件,修改如下:
const testMode = process.env.NODE_ENV === 'test'
module.exports = {
presets: ['@vue/cli-plugin-babel/preset']
presets: ['@vue/cli-plugin-babel/preset'],
plugins: testMode ? ['babel-plugin-istanbul'] : []
}
最后,打开 package.json 文件,修改 test:unit 命令:
"test:unit": "nyc vue-cli-service test:unit --reporter=mochawesome"
单元测试文件书写位置调整
如果我们的项目是一个去中心化的架构,我们可能希望我们的单元测试文件位于我们的组件旁边,而不是都写在 tests/unit/ 目录下。
在 tests/unit 目录下新建 index.spec.js 文件,其内容如下:
// require all src files that ends with .spec.js
const srcContext = require.context('../../src/', true, /\.spec.js$/)
srcContext.keys().forEach(srcContext)
修改.eslintrc.js 配置
overrides: [
{
files: [
'**/__tests__/*.{j,t}s?(x)',
'**/tests/unit/**/*.spec.{j,t}s?(x)',
'**/src/**/*.spec.{j,t}s?(x)'
],
env: {
mocha: true
}
}
]
至此,Vue+Mocha单元测试基本配置完成,执行test:unit 命令后,可在项目中查看测试效果
Vue & jest
项目创建
项目创建时选择 Jest 的Unit Testing,具体操作可查看Mocha的创建
添加测试报告
安装依赖:
npm i --save-dev jest-html-reporter
配置jest.config.js
jest集成了测试所需的功能,包括断言,覆盖率,以及测试报告等,测试配置文件如下:
module.exports = {
preset: '@vue/cli-plugin-unit-jest',
moduleFileExtensions: [
'js',
// 告诉 Jest 处理 `*.vue` 文件
'vue'
],
moduleNameMapper: {
// 支持源代码中相同的 `@` -> `src` 别名
'^@/(.*)$': '<rootDir>/src/$1'
},
transform: {
// 用 `babel-jest` 处理 `*.js` 文件
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
// 用 `vue-jest` 处理 `*.vue` 文件
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
},
testMatch: ['**/__tests__/**/*.[jt]s?(x)', '**/?(*.)+(spec|test).[jt]s?(x)', '**/src/**/*.spec.{j,t}s?(x)'],
snapshotSerializers: [
// 快照的序列化工具
'<rootDir>/node_modules/jest-serializer-vue'
],
displayName: {
name: 'CLIENT',
color: 'blue'
},
// 成多种格式的测试覆盖率报告 可选
collectCoverage: true,
collectCoverageFrom: ['**/*.{js,vue}', '!**/node_modules/**', '!**/dist/**', '!**/coverage/**'],
// report配置
reporters: [
'default',
[
'./node_modules/jest-html-reporter',
{
pageTitle: 'test report',
outputPath: 'testReport/JesttestReport.html',
includeFailureMsg: true
}
]
]
}
至此,Vue+Jest单元测试基本配置完成,执行test:unit 命令后,可在项目中查看测试效果。
Jest相对Mocha而言,配置简单许多,开箱即用,考虑到不同的库需要学习不同的API,踩坑的风险也随之提升,后续框架均只采用Jest进行配置。
Angular
Angular脚手架在创建项目时自动配置单元测试,采用Karma和Jasmine,引入Jest需要迁移
angular & Jest
配置时默认使用angular脚手架创建的项目
迁移
第一步,下载相关的依赖包:
npm i --save-dev jest jest-preset-angular @types/jest jest-html-reporter
第二步,在pakage.json中对Jest进行配置,也可直接配置jest.config.js
"jest": {
"preset": "jest-preset-angular",
"setupFilesAfterEnv": ["<rootDir>/src/setupJest.ts"]
}
第三步,在src目录下创建上一步中设置的 setup 文件setupJest.ts
import 'jest-preset-angular'; // jest 对于 angular 的预配置
接下来,我们就可以在 package.json 的 script 中配置 test 的命令了:
"test": "jest"
此时,在命令行中运行测试命令,就应该能够顺利把测试跑起来并通过了。如果没有通过,可能是因为我们在src/tsconfig.spec.json
中的 file 配置中有test.ts
的配置,这是 Karma 的 setup 文件,删掉这行配置并删除对应的文件,(src/tsconfig.app.json
中出现的test.ts
也可一并删除),重新执行npm run test
即可
删除 Karma 相关代码
- 删除相关依赖包(@types/jasmine @types/jasminewd2 jasmine-core jasmine-spec-reporter 因为在 e2e 测试中有使用所以不能删除):
npm uninstall karma karma-chrome-launcher karma-coverage-istanbul-reporter karma-jasmine karma-jasmine-html-reporter
- 删除文件
src/karma.config.js
- 删除 angular.json中test的配置
-
src/tsconfig.spec.json
和compilerOptions.type
的配置移除 jasmine, 加上 jest。
至此,Jest测试环境就算顺利搭建好了
React
Create React App创建后react项目后,是默认集成Jest的,所以我们只需完善配置即可
浅层渲染
如果你希望测试独立于它们渲染的子组件的组件,我们建议使用 Enzyme
的 shallow() 渲染API。
第一步,安装enzyme依赖
npm install --save-dev enzyme enzyme-adapter-react-16 react-test-renderer
第二步,修改src/setupTests.js
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
// 添加在测试中模拟的浏览器API
const localStorageMock = {
getItem: jest.fn(),
setItem: jest.fn(),
removeItem: jest.fn(),
clear: jest.fn(),
};
global.localStorage = localStorageMock;
覆盖率报告
Jest 有一个集成的覆盖率报告器,可以很好地与 ES6 配合使用,无需配置。运行 npm test -- --coverage