单元测试是项目开发中一个非常重要的环节,完整的测试能为代码和业务提供质量保证,减少 Bug 的出现。
下面带领大家在 Vite + Vue3 + TypeScript 的项目中集成单元测试工具。
安装核心依赖
我们使用 Vue 官方提供的 vue-test-utils 和社区流行的测试工具 jest 来进行 Vue 组件的单元测试。
- vue-test-utils The next iteration of Vue Test Utils. It targets Vue 3.
- jest Delightful JavaScript Testing.
- vue-jest Jest Vue transformer
- ts-jest A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript.
安装这些工具为开发依赖(devDependencies):
npm i @vue/test-utils@next jest vue-jest@next ts-jest -D
npm i @vue/test-utils@next jest vue-jest@next ts-jest -D
创建 jest 配置文件
在项目根目录下新建 jest.config.js 文件:
module.exports = {
moduleFileExtensions: ['vue', 'js', 'ts'],
preset: 'ts-jest',
testEnvironment: 'jsdom',
transform: {
'^.+\\.vue$': 'vue-jest',
// vue 文件用 vue-jest 转换
'^.+\\.ts$': 'ts-jest',
// ts 文件用 ts-jest 转换
},
// 匹配 __tests__ 目录下的 .js/.ts 文件 或其他目录下的 xx.test.js/ts xx.spec.js/ts
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(ts)$',
}
module.exports = {
moduleFileExtensions: ['vue', 'js', 'ts'],
preset: 'ts-jest',
testEnvironment: 'jsdom',
transform: {
'^.+\\.vue$': 'vue-jest',
// vue 文件用 vue-jest 转换
'^.+\\.ts$': 'ts-jest',
// ts 文件用 ts-jest 转换
},
// 匹配 __tests__ 目录下的 .js/.ts 文件 或其他目录下的 xx.test.js/ts xx.spec.js/ts
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(ts)$',
}
创建单元测试文件
在上面的 jest.config.js 文件中,我们配置只匹配 tests 目录下的任意 .ts 文件或其他目录下的 xx.test.ts/xx.spec.ts 文件进行单元测试。
这里,我们在项目根目录下创建 tests 目录来存储单元测试文件
├── src/
└── tests/ // 单元测试目录
├── Test.spec.ts // Test 组件测试
├── src/
└── tests/ // 单元测试目录
├── Test.spec.ts // Test 组件测试
- Test.vue
<template>
<div class="test-container page-container">
<div class="page-title">Unit Test Page</div>
<p>count is: {{ count }}</p>
<button @click="increment">increment</button>
</div>
</template>
<script lang="ts">
import {defineComponent, ref} from 'vue'
export default defineComponent({
name: 'Vuex',
setup() {
const count = ref<number>(0)
const increment = () => {
count.value += 1
}
return {count, increment}
},
})
</script>
<template>
<div class="test-container page-container">
<div class="page-title">Unit Test Page</div>
<p>count is: {{ count }}</p>
<button @click="increment">increment</button>
</div>
</template>
<script lang="ts">
import {defineComponent, ref} from 'vue'
export default defineComponent({
name: 'Vuex',
setup() {
const count = ref<number>(0)
const increment = () => {
count.value += 1
}
return {count, increment}
},
})
</script>
- Test.spec.ts
import {mount} from '@vue/test-utils'
import Test from '../src/views/Test.vue'
test('Test.vue', async () => {
const wrapper = mount(Test)
expect(wrapper.html()).toContain('Unit Test Page')
expect(wrapper.html()).toContain('count is: 0')
await wrapper.find('button').trigger('click')
expect(wrapper.html()).toContain('count is: 1')
})
import {mount} from '@vue/test-utils'
import Test from '../src/views/Test.vue'
test('Test.vue', async () => {
const wrapper = mount(Test)
expect(wrapper.html()).toContain('Unit Test Page')
expect(wrapper.html()).toContain('count is: 0')
await wrapper.find('button').trigger('click')
expect(wrapper.html()).toContain('count is: 1')
})
集成 @types/jest
如上图,我们使用 VSCode / WebStrom / IDEA 等编辑器时,在单元测试文件中,IDE 会提示某些方法不存在(如 test、describe、it、expect 等),安装 @types/jest 即可解决。
npm i @types/jest -D
npm i @types/jest -D
TypeScript 的编译器也会提示 jest 的方法和类型找不到,我们还需把 @types/jest 添加根目录下的 ts.config.json(TypeScript 配置文件)中:
{
"compilerOptions": {
...
"types": ["vite/client", "jest"]
},
}
{
"compilerOptions": {
...
"types": ["vite/client", "jest"]
},
}
添加 eslint-plugin-jest
因为我们在项目中集成了 ESLint,如上图很明显是没通过 ESLint 规则检验。因此,我们还需要在 ESLint 中增加 eslint-plugin-jest 插件来解除对 jest 的校验。
- 安装 eslint-plugin-jestnpm i eslint-plugin-jest -D
- 添加 eslint-plugin-jest 到 ESLint 配置文件 .eslintrc.js 中
module.exports = {
...
extends: [
...
'plugin:jest/recommended'
],
...
}
module.exports = {
...
extends: [
...
'plugin:jest/recommended'
],
...
}
现在,我们的单元测试代码就不会有错误提示信息了 ؏؏☝ᖗ 乛 ◡ 乛 ᖘ☝؏؏
执行单元测试
在根目录下 package.json 文件的 scripts 中,添加一条单元测试命令: "test": "jest"。
执行命令 npm run test 即可进行单元测试,jest 会根据 jest.config.js 配置文件去查找 tests 目录下的 .ts 文件或其他任意目录下的 .spec.ts 和 .test.ts 文件,然后执行单元测试方法。
你可以在 jest.config.js 配置文件中,自由配置单元测试文件的目录。
- 单元测试全部通过时的终端显示信息
- 单元测试未全部通过时的终端显示信息
当单元测试没有全部通过时,我们需要根据报错信息去优化对应组件的代码,进一步提高项目健壮性。但是写单元测试是件比较痛苦的事,我个人觉得也没必要全部组件都写单元测试,根据项目实际情况有针对性去写就行了。
单元测试约束
前面,我们使用 husky 在 Git 的 pre-commit 和 commit-msg 阶段分别约束代码风格规范和提交信息规范。这一步,我们在 pre-push 阶段进行单元测试,只有单元测试全部通过才让代码 push 到远端仓库,否则终止 push。
使用 husky 命令在 .husky 目录下自动创建 pre-push hook 文件,并在此执行单元测试命令 npm run test。
npx husky add .husky/pre-push "npm run test $1"
npx husky add .husky/pre-push "npm run test $1"