测试Button组件
Vitest 是一个由 Vite 社区开发的测试框架,专门为 Vite 项目设计。它使得在 Vite 项目中进行单元测试变得更加容易。
Vitest 的主要特性包括:
-
针对 Vite 优化:由于 Vitest 是为 Vite 项目设计的,所以它能够无缝地与 Vite 项目集成,处理 Vite 的配置,并能够正确地处理 Vite 插件。
-
支持多种测试环境:Vitest 支持在多种环境下运行测试,包括 Node.js 环境、浏览器环境。
-
并发测试:Vitest 支持并行运行测试,可以大大提高测试的速度。
-
丰富的断言库:Vitest 内置了一个断言库,提供了丰富的断言方法,使得编写测试变得更加方便。
-
支持源码映射(Source Map):Vitest 支持源码映射,这使得当测试失败时,你可以在控制台看到原始代码的行号,而不是编译后代码的行号。
-
集成测试覆盖率报告:Vitest 能够生成测试覆盖率报告,帮助你理解你的测试覆盖了代码的哪些部分,哪些部分还没有被覆盖。
Vitest 官网:vitest.dev/
准备工作
首先第一步,我们需要安装 vitest,这里选择安装到工作空间里面:
pnpm add vite vitest jsdom @vitejs/plugin-vue @vue/test-utils -D -w
除了 vitest 测试框架以外,我们还安装:
- jsdom:这个库可以模拟出一个类似于浏览器的环境,我们可以使用 jsdom 提供的 api 来操作和查询 dom,就像在真实的浏览器环境里面一样。
- @vitejs/plugin-vue:这个是 vite 的一个插件,该插件提供了对 vue3 的支持,通过该插件,vite 能够处理单文件类型的 vue 组件
- @vue/test-utils:这是 vue 官方所提供的一个库,里面提供了各种 api,用于做单元测试。
接下来在 packages/components 项目下面创建:
- vite.config.js:vite 的配置文件
- vitest.config.js:vitest 的配置文件
vite.config.js
// 从 node.js 内置的 url 模块中引入 fileURLToPath、URL
// 这两个函数用于做 URL 相关的处理
import { fileURLToPath, URL } from "node:url";
// 从 vite 里面引入 defineConfig,该方法用于定义 vite 配置
import { defineConfig } from "vite";
// 引入 @vitejs/plugin-vue 这个插件,让 vite 能够支持对 vue 的处理
import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/
export default defineConfig({
// 要使用的插件
plugins: [vue()],
resolve: {
// 定义了一个别名映射
// @ ---> src
alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)),
},
},
});
vitest.config.js
import { mergeConfig, defineConfig } from "vite";
// 引入 vite.config.js 中导出的配置
import viteConfig from "./vite.config";
export default mergeConfig(
viteConfig,
defineConfig({
test: {
environment: "jsdom",
},
})
);
期间会存在报 File '@tsconfig/node18/tsconfig.json' not found. 的错误,把 @tsconfig/node18 这个库安装一下即可:
pnpm add @tsconfig/node22 -D -w
在 packages/components/package.json 中添加了 "type": "module" 来告诉 Node.js 这个包使用 ES 模块
packages/components/package.json
{
"type": "module"
}
编写测试用例
在 packages/components/button目录下面创建 test 目录,并且在 test 目录下面创建 button.test.ts
代码如下:
// 该文件用于书写测试用例
import { describe, it, expect } from "vitest";
import { mount } from "@vue/test-utils";
import Button from "../src/button.vue";
describe("测试 Button 组件", () => {
// 一个一个的测试用例
it("渲染按钮的时候有默认type", () => {
// 准备工作
const wrapper = mount(Button);
// 断言
expect(wrapper.classes()).toContain("fux-button");
expect(wrapper.classes()).toContain("fux-button-default");
});
it("渲染按钮有正确的属性", () => {
// 准备工作
const wrapper = mount(Button, {
props: {
type: "primary",
},
});
// 断言
expect(wrapper.classes()).toContain("fux-button");
expect(wrapper.classes()).toContain("fux-button-primary");
});
it("渲染plain类型的按钮", () => {
// 准备工作
const wrapper = mount(Button, {
props: {
plain: true,
},
});
// 断言
expect(wrapper.classes()).toContain("is-plain");
});
it("渲染round类型的按钮", () => {
const wrapper = mount(Button, { props: { round: true } });
expect(wrapper.classes()).toContain("is-round");
});
it("渲染circle类型按钮", () => {
const wrapper = mount(Button, { props: { circle: true } });
expect(wrapper.classes()).toContain("is-circle");
});
it("渲染disabled类型按钮", () => {
const wrapper = mount(Button, { props: { disabled: true } });
expect(wrapper.classes()).toContain("is-disabled");
expect(wrapper.attributes()).toHaveProperty("disabled");
});
it("渲染icon类型的按钮", () => {
const wrapper = mount(Button, { props: { icon: "home" } });
expect(wrapper.find("i").classes()).toContain("fux-icon-home");
});
it("测试 slot 插槽是否正常工作", () => {
const wrapper = mount(Button, {
slots: {
default: "点击我",
},
});
expect(wrapper.text()).toContain("点击我");
});
// 测试事件是否工作正常
it("测试按钮事件", async ()=>{
const wrapper = mount(Button);
await wrapper.trigger("click");
expect(wrapper.emitted()).toHaveProperty("click");
});
});
之后在 components/package.json 中,添加命令脚本:
"scripts": {
"test": "vitest"
},
最后在根目录下面的 package.json 中添加如下的命令脚本:
"scripts": {
...
"test": "pnpm -C packages/components test"
},
之后就可以在项目根目录下运行 pnpm test 来进行组件的测试。