Appearance
从0到1搭建Vue组件库07:给组件库项目增加单元测试
Vue DevUI是一个通过开源社区孵化的 Vue3 开源组件库,这意味着从一开始Vue DevUI
就不是靠个人维护的项目,而是通过社区共同的力量进行持续演进的。
由于是新项目,在技术选型时,我们都是用的最新的技术:
- 用
Vite
搭建基础工程和构建打包 - 用最新的
Vue3
语法编写组件 - 用
TypeScript
给代码增加类型系统 - 用
JSX
语法编写Vue组件,确保最大的灵活性 - 用
VitePress
搭建组件库的文档
刚开始我们只是搭了一个架子,写了一些组件,加了commit
检查,工程化方面的东西还很不完善,没有单元测试、没有eslint
、没有cli
工具。
社区的小伙伴 Brenner 发现了这个问题,作为一个开源项目,怎么能没有单元测试呢?后面正式发布了,别人一看,单元测试都没有,还敢用吗?
所以Brenner
同学在2021年6月13日,正式提交了一个PR,给Vue DevUI
增加了基于Jest和Vue Test Utils的单元测试环境。
Brenner 是我们的早期贡献者,vue devui
于2021.5.1
正式在掘金招募contributor
。
当时其实响应的人不算多,直到Brenner的出现,Brenner
同学在6月13日悄悄地给vue devui
提交了一个pr:
https://gitee.com/devui/vue-devui/pulls/4
之后几乎每隔一个星期都有提交pr,完善了单元测试、eslint等代码检查工具,并提交了好几个组件,比如:
- Radio
- Checkbox
- Switch
- TagInput
- Input
Brenner
同学给了我很大的信心,虽然现在Brenner
同学已经退居幕后,但正是因为他的早期的持续贡献,让vue devui
有个重大突破。
2个月之后的8月3日,vue devui的组件数量达到10个,我们在掘金同步了这个消息。
之后vue devui开始活跃,涌现了大量的田主和contributor。
让我们一起来看看,如何给Vue3组件库搭建单元测试环境,并给Vue组件增加单元测试。
1 引入 Jest
1.1 安装 Jest
yarn add -D jest @types/jest
1.2 增加脚本命令
package.json
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"serve": "vite preview",
"test": "jest" // 新增
},
1.3 编写测试用例
// Step 1: 定义一个测试套 Test Suite
describe('tree', () => {
// Step 2: 定义一个单元测试 Test
// i think 'tree should render correctly'
it('tree should render correctly', () => {
// Step 3: 期望(expect)tree组件的class里面包含(toContain)'devui-tree'
expect(wrapper.classes()).toContain('devui-tree')
// 期望(expect)tree组件的子元素数量为(toBe)6
expect(wrapper.element.childElementCount).toBe(6)
})
})
1.4 编写第一个单元测试
devui/tree/__tests__/tree.spec.ts
// Step 1: 定义一个测试套 Test Suite
describe('tree', () => {
// Step 2: 定义一个单元测试 Test
// i think 'tree should render correctly'
it('should render correctly', () => {
// Step 3: 编写测试断言,期望(expect)1等于1
expect(1).toEqual(1)
})
})
1.5 执行 test 命令
yarn test
2 测试组件
2.1 安装@vue/test-utils
yarn add -D @vue/test-utils
2.2 编写组件测试代码
devui/tree/__tests__/tree.spec.ts
import { mount } from '@vue/test-utils'
import DTree from '../src/tree'
describe('tree', () => {
it('should render correctly', () => {
const wrapper = mount({
components: { DTree },
template: `
<d-tree :data="data"></d-tree>
`,
setup() {
const data = [{
label: '一级 1', level: 1,
children: [{
label: '二级 1-1', level: 2,
children: [{
label: '三级 1-1-1', level: 3,
}]
}]
}, {
label: '一级 2', level: 1,
open: true, // 新增
children: [{
label: '二级 2-1', level: 2,
children: [{
label: '三级 2-1-1', level: 3,
}]
}, {
label: '二级 2-2', level: 2,
children: [{
label: '三级 2-2-1', level: 3,
}]
}]
}, {
label: '一级 3', level: 1,
open: true, // 新增
children: [{
label: '二级 3-1', level: 2,
children: [{
label: '三级 3-1-1', level: 3,
}]
}, {
label: '二级 3-2', level: 2,
open: true, // 新增
children: [{
label: '三级 3-2-1', level: 3,
}]
}]
}, {
label: '一级 4', level: 1,
}]
return {
data
}
}
})
expect(wrapper.classes()).toContain('devui-tree')
})
})
再重新执行yarn test
命令,发现报错啦~
3 遇到的问题及相应的解法
3.1 第一个报错:SyntaxError: Cannot use import statement outside a module
这是一个比较典型的问题,jest解析文件过程中遇到的语法问题。
报错信息也提示了可能的原因和解法:
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
大意是你可能引入了ES6
、TypeScript
,但是又没有配置相应的transform
转换器。
安装 babel-jest
先安装依赖babel-jest
和@babel/preset-env
yarn add -D babel-jest @babel/preset-env
配置 jest transform
jest.config.js
module.exports = {
transform: {
'^.+\\.(ts|tsx|js|jsx)$': [
'babel-jest', { presets: ['@babel/preset-env'] }
]
},
};
再重新执行yarn test
命令,发现又报错啦
~
3.2 第二个报错:Cannot find module 'vue-template-compiler'
这个问题其实是没有安装正确的@vue/test-utils
导致的,默认安装的是vue2版本的@vue/test-utils
,但我们是vue3组件库,需要安装@vue/test-utils@next
。
我们先按照报错提示安装下vue-template-compiler
试试看。
安装依赖 vue-template-compiler
yarn add -D vue-template-compiler
再重新执行yarn test
命令,发现又双报错啦
~
3.3 第三个报错:Vue packages version mismatch
果然不是vue-template-compiler
的问题,不过这个提示倒是提醒我们是版本不匹配的问题。
安装Vue3版本的@vue/test-utils@next
yarn add -D @vue/test-utils@next
再重新执行yarn test
命令,发现又双叒报错啦
~
接下来是一系列的语法错误SyntaxError
,都是没有配置相应的transform转换器导致的。
3.4 第四个报错:SyntaxError: Unexpected token, expected ","
安装 @babel/preset-typescript
yarn add -D @babel/preset-typescript
配置 @babel/preset-typescript
jest.config.js
module.exports = {
transform: {
'^.+\\.(ts|tsx|js|jsx)$': [
'babel-jest', {
presets: [
'@babel/preset-env',
'@babel/preset-typescript' // 新增
]
}
]
},
};
重新执行yarn test
命令,还是报错~
3.5 第五个报错:SyntaxError: Unexpected token '<'
安装 @vue/babel-plugin-jsx
yarn add -D @vue/babel-plugin-jsx
配置 @vue/babel-plugin-jsx
jest.config.js
module.exports = {
transform: {
'^.+\\.(ts|tsx|js|jsx)$': [
'babel-jest', {
presets: [
'@babel/preset-env',
'@babel/preset-typescript'
],
plugins: ['@vue/babel-plugin-jsx'] // 新增
}
]
},
};
继续执行yarn test
命令,还是报错~
3.6 第六个报错:SyntaxError: Invalid or unexpected token
修改样式导入
import './tree.scss'
->
import './tree'
再重新执行yarn test
命令,发现又双叒叕报错啦
~
3.7 第七个错:ReferenceError: document is not defined
这个报错提示得很清楚:
The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/configuration#testenvironment-string.
Consider using the "jsdom" test environment.
测试环境错误,需要配置jsdom
的测试环境。
修改测试环境 testEnvironment
jest.config.js
testEnvironment: 'jest-environment-jsdom',
终于成功了!
此处应该庆祝一下🎉!
小结
本文主要分享搭建vue3组件库单元测试环境的步骤、遇到的问题及相应的解法。
- 引入
jest
支持基本的单元测试 - 引入
@vue/test-utils
支持vue组件的单元测试 - 配置
jest.config.js
,增加@babel/preset-env
和@babel/preset-typescript
两个preset
以支持ES6
和TS
语法,以及一个@vue/babel-plugin-jsx
plugin 以支持JSX
语法 - 配置
testEnvironment
为jest-environment-jsdom
- 编写单元测试的三部曲:
测试套
、单元测试
、测试断言
- 分析了搭建单元测试环境中遇到的典型问题及相应的解决方案
发布时间: