为什么选择 Vitest ?
一个是因为 Vitest
基于 Vite
并能重复使用 Vite
的配置、转换器、解析器和插件,以及开箱即用的 TypeScript
/ JSX
支持等特点把我的目光从 Jest
中夺了过去(翻译翻译就是它又快配置又简单,这种框架谁不喜欢呢?)
二个是因为作者是 Anthony Fu
大佬
官方地址留给你们后续查资料
上手指南从这里开始了啊
Vitest 安装
提示:Vitest 需要 Vite >=v3.0.0 和 Node >=v14
然后根据自己的项目选择其中一种安装方式就行,最好不要混用哦
npm install -D vitest
yarn add -D vitest
pnpm add -D vitest
执行完安装命令后,你的 package.json
文件中 devDependencies
下就会出现 "vitest": "^x.x.x"
,也代表你安装成功了!
Vitest 配置
Vitest
可以直接读取你的 vite.config.ts
文件,所以你其实并不需要单独建立 vitest.config.ts
文件了。
在 vite.config.ts
文件中,我们将 import { defineConfig } from "vite"
替换成 import { defineConfig } from "vitest/config"
,然后在配置中新增一个 test
属性就完成了写配置最基本的结构:
import { defineConfig } from "vitest/config"
export default defineConfig({
test: { // ... }
})
假如你并不想替换 import { defineConfig } from "vite"
,或者你的项目根本没有用到 import { defineConfig } from "vite"
,这时候有没有其他办法呢?
答案当然是有的,你可以在 vite.config.ts
文件的最顶部(第一行)加上三斜线命令:/// <reference types="vitest" />
即可!
我自己的项目就是采用的添加三斜线命令的方式来进行配置的:
/// <reference types="vitest" />
import { defineConfig } from "vite"
export default defineConfig({
test: { // ... }
})
TS 配置
如果你的项目是基于 TypeScript 的,那么你还应该在 tsconfig.json
文件的 compilerOptions.types
配置中添加:"vitest"
和 "vitest/globals"
,如下:
{
"compilerOptions": {
"types": [
"vitest",
"vitest/globals"
]
}
}
Vitest 运行
现在你需要在你的 package.json
文件中 scripts
下新增 "test": "vitest"
脚本:
{
"scripts": {
"test": "vitest"
}
}
然后后续你要进行单元测试的时候,执行 npm run test
、yarn test
、pnpm test
命令就行了。
Vitest 语法
建立测试文件
可以去项目根目录建立一个名为 tests
的文件夹,然后在里面建立一个名为 demo.test.ts
的测试文件。其中 demo
是文件名称,.test.ts
是特殊的后缀。
维护 Vitest 配置
由于以后我们都会将测试文件放在 tests
文件夹下,所以我们可以将 Vitest
配置修改为:
test: {
include: ["tests/**/*.test.ts"]
}
这代表 Vitest
将去 tests
文件夹下面寻找 .test.ts
后缀的测试文件。
编写测试用例
我们在 demo.test.ts
测试文件中写入如下测试代码:
import { describe, expect, it } from "vitest"
const author1 = {
name: "pany",
email: "939630029@qq.com",
url: "https://github.com/pany-ang"
}
const author2 = {
name: "pany",
email: "939630029@qq.com",
url: "https://github.com/pany-ang"
}
describe("这里填写作用域名称", () => {
it("测试基础数据类型", () => {
expect(1 + 1).toBe(2)
})
it("测试引用类型", () => {
expect(author1).toEqual(author2)
})
})
Vitest API 解释
describe
:形成一个作用域test
/it
:定义了一组关于测试期望的方法,它接收测试名称和一个含有测试期望的函数expect
:创建断言toBe
:可用于断言基础对象是否相等,或者对象是否共享相同的引用toEqual
:断言检查值是否等于接收值,或者是同样的结构,如果是对象类型(将会使用递归的方法进行比较)
执行命令测试
我们这时候执行 npm run test
、yarn test
、pnpm test
命令就可以得到该测试文件的测试结果,如下图:
代表通过测试。这时候我们去修改一下测试代码,将 expect(1 + 1).toBe(2)
修改为 expect(1 + 1).toBe(3)
,可以得到如下报错信息:
并且从报错信息中,我们可以清楚的定位到是测试基础数据类型
这个用例发生了错误,然后通过 Expected
和 Received
,也可以清楚看见结果值和预期值之间的差异。
Vitest 实战
我们用 Vitest 来测试 Vue 的组件,来模拟一下真实的单元测试。
维护 Vitest 配置
在上文中,我们已经将配置修改为:
test: {
include: ["tests/**/*.test.ts"]
}
然后这里我们要将它再次修改为这样:
test: {
include: ["tests/**/*.test.ts"],
environment: "jsdom"
}
这代表着,我们将用 jsdom
这个库,在本地 Node 环境中模拟浏览器的 DOM 环境(因为我们要开始测 Vue 组件啦)
安装依赖
到这里我们要继续新增一些依赖,第一个就是上文提到的 jsdom
,第二个是 @vue/test-utils
# 用 pnpm 命令举例安装
pnpm add -D jsdom
pnpm add -D @vue/test-utils
安装 @vue/test-utils
是因为 Vitest 本身是不支持 Vue 组件单元测试的,需要安装它来配合测试。
编写测试用例
假如我们要测试的组件名为 Notify.vue
,那么我们就可以在 tests
文件夹下面建立一个名为 Notify.test.ts
的测试文件,然后写入如下测试代码:
(当然,由于你们没有我的 Notify.vue 组件,所以你们直接复制下面测试代码是会报错的,我在文末会放上开源链接,大家可以下载下来运行 pnpm test 查看效果。文章这里的话,大家只需要学 API 语法即可)
import { shallowMount } from "@vue/test-utils"
import { describe, expect, it } from "vitest"
import Notify from "@/components/Notify/index.vue"
import NotifyList from "@/components/Notify/NotifyList.vue"
describe("Notify", () => {
it("正常渲染", () => {
const wrapper = shallowMount(Notify)
expect(wrapper.classes("notify")).toBe(true)
})
})
describe("NotifyList", () => {
it("List 长度为 0", () => {
const wrapper = shallowMount(NotifyList, {
props: {
list: []
}
})
expect(wrapper.find("el-empty").exists()).toBe(true)
})
it("List 长度不为 0", () => {
const wrapper = shallowMount(NotifyList, {
props: {
list: [
{
title: ""
}
]
}
})
expect(wrapper.find("el-empty").exists()).toBe(false)
})
})
Vitest API 解释
describe
:形成一个作用域test
/it
:定义了一组关于测试期望的方法,它接收测试名称和一个含有测试期望的函数expect
:创建断言toBe
:可用于断言基础对象是否相等,或者对象是否共享相同的引用toEqual
:断言检查值是否等于接收值,或者是同样的结构,如果是对象类型(将会使用递归的方法进行比较)
Vue Test Utils API 解释
shallowMount
:创建一个包含被挂载和渲染的 Vue 组件的 Wrapper(shallowMount 只会渲染当前组件,而不会渲染它的子组件)shallowMount 的第二个参数
:可以传递 slots、props 等参数模拟真实情况classes("notify")
:如果有名为 notify 的类名,则返回 true,反之则返回 falsefind
:返回匹配选择器的第一个 DOM 节点或 Vue 组件的 Wrapperexists
:断言 Wrapper 或 WrapperArray 是否存在
开源代码
这个开源中后台管理系统模板就按照本文的方式集成好了 Vitest,并编写好了一些测试用例可供大家参考。
克隆下来并安装依赖后,运行 pnpm test,就可以体验集成好的 Vitest 了。