Vue单元测试
- 新建一个vue项目
# 1.创建项目
vue create vue-jest-demo # 新建一个vue的项目(选择jest单元测试)
# 2.选择自定义配置
default (babel, eslint)
> Manually select features
# 3.选择安装feature,也可以根据自己的喜好去安装
(*) Babel
( ) TypeScript
( ) Progressive Web App (PWA) Support
(*) Router
(*) Vuex
(*) CSS Pre-processors
(*) Linter / Formatter
>(*) Unit Testing
( ) E2E Testing
# 选择测试框架,我们选择jest
Mocha + Chai
>(*) Jest
安装完毕后,会在根目录下存在一个 tests 的目录,其中里面包含一个简单的测试用例 example.spec.js 文件 和 jest.config.js 单元测试配置文件
- 项目目录结构
LiuJun-MacBook-Pro:vue-test-demo liujun$ tree
.
├── README.md
├── babel.config.js
├── jest.config.js # 单元测试的配置
├── package-lock.json
├── package.json # 项目的依赖
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ └── HelloWorld.vue
│ ├── main.js
│ ├── router
│ │ └── index.js
│ ├── store
│ │ └── index.js
│ └── views
│ ├── About.vue
│ └── Home.vue
└── tests # 单元测试的文件
└── unit
└── example.spec.js
项目的package.json文件
{
"name": "vue-test-demo",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"test:unit": "vue-cli-service test:unit",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^2.6.11",
"vue-router": "^3.2.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/cli-plugin-unit-jest": "~4.5.0",
"@vue/test-utils": "^1.0.3",
"@vue/eslint-config-standard": "^5.1.2",
"@vue/cli-plugin-eslint": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.0",
"eslint-plugin-vue": "^6.2.2",
"node-sass": "^4.12.0",
"sass-loader": "^8.0.2",
"vue-template-compiler": "^2.6.11"
}
}
项目 jest.config.json 文件的配置
module.exports = {
preset: '@vue/cli-plugin-unit-jest'
}
- 运行单元测试
npm run test:unit
# 控制台输出的结果
LiuJun-MacBook-Pro:vue-test-demo liujun$ npm run test:unit
> vue-test-demo@0.1.0 test:unit /Users/liujun/Documents/huayun/test/vue-test-demo
> vue-cli-service test:unit
PASS tests/unit/example.spec.js
HelloWorld.vue
✓ renders props.msg when passed (40ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.595s
Ran all test suites.
- 配置测试覆盖率和测试报告
在根目录下的 jest.config.js 中,进行如下配置:
module.exports = {
preset: '@vue/cli-plugin-unit-jest',
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1"
},
testMatch: [
"**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"
],
collectCoverage: true,
coverageDirectory: "<rootDir>/tests/unit/coverage",
collectCoverageFrom: [
"src/components/**/*.vue",
"src/utils/**/*.ts",
"src/store/modules/*.ts",
"!src/utils/axios.ts",
"!src/utils/notify.ts"
]
}
配置的解释如下:
-
preset: 预设的vue单元测试使用的插件。
-
moduleNameMapper:模块别名配置。
-
testMatch:测试文件查找规则,可以是统一放在src/tests目录下,也可以就近放在_ _tests__目录下。
-
collectCoverage:是否进行测试覆盖率收集。
-
coverageDirectory:测试报告存放位置。
-
collectCoverageFrom:测试哪些文件和不测试哪些文件,你可以根据你的团队或者个人偏好进行设置。
在完善以上配置后,在终端运行npm run test:unit命令,可看测试覆盖率和测试报告。
> vue-cli-service test:unit
PASS tests/unit/example.spec.js
HelloWorld.vue
✓ renders props.msg when passed (36ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 0 | 0 | 0 | 0 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 5.17s
Ran all test suites.
测试HelloWorld组件
1.简单测试HelloWorld组件
1.编写 HelloWorld.vue组件
<template>
<div class="hello">
<slot name="title">
<span>count:{
{count}}</span>
</slot>
<button
class="btn btn-primary"
:style="{height:'50px'}"
@click="handlerBtnClick">
{
{msg}}
</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String,
defaultCount: {
type: Number,
default: 0
}
},
data () {
return {
count: this.defaultCount
}
},
methods: {
handlerBtnClick () {
this.count = this.count + 1
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang