参考地址:
一、安装和配置插件
(一) 安装插件
npm i vitest happy-dom c8 @vitest/coverage-c8 @vue/test-utils -D
vitest核心插件happy-dom模拟Web浏览器,以便用于测试的工具c8&@vitest/coverage-c8用于展示测试覆盖率@vue/test-utils提供一个mount方法,用于实例化一个组件
(二) 配置
1、vite.config.ts
可以在 vite.config.ts 的 test 属性下进行 vitest 的相关配置。配置之前我们需要在文件顶部配置 三条斜线 命令告诉编译器在编译过程中引入额外的文件。
/// <reference types="vitest" />
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue"
...
export default defineConfig(
{
...
test: {
environment: "happy-dom",
coverage: {
provider: 'c8', // or 'c8'
reporter: ['text', 'json', 'html'],
},
},
}
)
2、package.json
"scripts": {
"test": "vitest",
"coverage": "vitest run --coverage" // 生成覆盖率报告
}
3、命令解释
1、执行一个特定的测试文件
npx vitest 文件名
vitest会寻找**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}形式的文件。
2、执行所有的测试文件
npm run test
举个例子
测试 Icon 组件,icon.test.ts。
- describe 描述,
describe会形成一个作用域 - it 断言
- expect 期望
- mount 用于实例化一个组件
import {describe,expect,it} from 'vitest'
import {mount} from '@vue/test-utils' // mount 用于实例化一个组件
import icon from '../src/components/icon'
describe('test Icon',function() {
it('class should contain "ivu-icon-ios-add"',function() {
const wrapper = mount(icon,{
props:{
type: 'ios-add'
}
})
expect(wrapper.classes()).toContain('ivu-icon-ios-add')
})
it('style should contain "font-size: 24px;"',function() {
const wrapper = mount(icon, {
props: {
size: 24
}
})
expect(wrapper.attributes('style')).toBe('font-size: 24px;')
})
it('style should containe "color: red;"',function() {
const wrapper = mount(icon,{
props: {
color: 'red'
}
})
expect(wrapper.attributes('style')).toBe('color: red;')
})
})
执行命令 npx vitest icon 就会执行这个测试文件。
二、复杂组件的测试
以 Button 组件的测试为例:button.test.js
import { describe, it, expect } from 'vitest';
import { mount } from '@vue/test-utils';
import button from '../src/components/button';
describe('test button', function () {
it('html shuold be "BUTTON" ', function () {
const wrapper = mount(button);
expect(wrapper.element.tagName).toBe('BUTTON');
});
it('class contain "ivu-btn-default"', function () {
const wrapper = mount(button);
expect(wrapper.classes()).toContain('ivu-btn-default');
});
// https://cn.vitest.dev/guide/migration.html
// 从 Vitest v0.10.0 开始,声明测试的回调样式被弃用。 你可以重写它们以使用 async/await 函数,或者使用 Promise 来模仿回调样式。
it('should change loading state', () =>
new Promise(async (done) => {
const Component = {
template: `
<Button type="primary" :loading="loading" @click="onChangeLoading" ref="btnEl">loading</Button>
`,
components: {
Button: button,
},
data() {
return {
loading: false,
};
},
methods: {
onChangeLoading() {
this.loading = true;
},
},
};
const wrapper = mount(Component);
await wrapper.vm.$el.click();
wrapper.vm.$nextTick(() => {
expect(wrapper.classes()).toContain('ivu-btn-loading');
const $icons = wrapper.findAll('.ivu-icon');
expect($icons.length).to.equal(1);
expect($icons[0].classes()).toContain('ivu-load-loop');
expect($icons[0].classes()).toContain('ivu-icon-ios-loading');
done(true);
});
}));
// 这样使用 终端 ui 界面显示 测试 通过,同时报错
// it('should change loading state', async (done) => {
// const Component = {
// template: `
// <Button type="primary" :loading="loading" @click="onChangeLoading" ref="btnEl">loading</Button>
// `,
// components: {
// Button: button,
// },
// data() {
// return {
// loading: false,
// };
// },
// methods: {
// onChangeLoading() {
// this.loading = true;
// },
// },
// };
// const wrapper = mount(Component);
// await wrapper.vm.$el.click();
// wrapper.vm.$nextTick(() => {
// expect(wrapper.classes()).toContain('ivu-btn-loading');
// const $icons = wrapper.findAll('.ivu-icon');
// expect($icons.length).to.equal(1);
// expect($icons[0].classes()).toContain('ivu-load-loop');
// expect($icons[0].classes()).toContain('ivu-icon-ios-loadin');
// // done(true); // done 被废弃
// });
// });
});