1. 为什么要进行单元测试?
- 测试的目的为了确保代码执行达到预期效果
- 可测试的代码可读性相对高一些,提高开发者写代码的质量
- 减少 Bug 率
2. 开发环境
node 14.17.0
vue 3.x
3. 在项目中集成
3.1 安装以及配置 jest
首先安装 Jest 和 @vue/test-utils
pnpm install --save-dev jest@26 ts-jest @types/jest
接下来,package.json中我们配置脚本
// package.json
{
"scripts": {
"test": "jest"
}
}
tsconfig.json 配置
{
// ...
"types": ["webpack-env", "jest"],
// ...
}
3.2 在 Jest 中处理 vue 文件
要告诉 Jest 处理 .vue以及 .ts|.tsx 文件,需要安装和配置预处理器。
pnpm install --save-dev vue-jest ts-jest@26 @testing-library/vue@next
然后修改/新增 jest.config.js 文件
// jest.config.js
module.exports = {
// ...
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
'\\.(vue)$': 'vue-jest',
},
// ...
}
3.3 处理别名
如果想要使用别名,需要增加 Jest 配置 moduleNameMapper
// jest.config.js
module.exports = {
// ...
moduleNameMapper: {
"^@/(.*)$": "<rootDir>/src/$1"
},
// ...
}
3.4 babel 设定
安装 @babel/preset-env
pnpm install --save-dev @babel/preset-env
babel.config.js 配置
module.exports = {
presets: [
[
"@babel/preset-env",
{
targets: {
node: "current",
},
},
],
],
};
3.5 生成报导文件
"test": "jest --coverage"
在 package.json 的执行命令增加 --coverage 告诉 Jest 生存测试报导,约定生成报道的地址可以通过设置coverageDirectory。
// jest.config.js
module.exports = {
// ...
coverageDirectory: './__test__/coverage',
// ...
}
默认情况下 Jest 会获取项目中所有的
.test.js文件,但是为了测试文件方便管理可以新建一个专门用于测试的目录。通过在 jest.config.js 中testMatch配置,去实现,例如testMatch: ["/tests/**/*.spec.[jt]s?(x)"]
4. 写一个简单的 Demo 示例
新建文件 Counter.vue
// src/components/Counter.vue
<template>
<div>
<p>Times clicked: {{ count }}</p>
<button @click="increment">increment</button>
</div>
</template>
<script>
import { defineComponent } from "vue";
export default defineComponent({
name: "Counter",
data: () => ({
count: 0,
}),
methods: {
increment() {
this.count++;
},
},
});
</script>
测试用例代码 counter.test.ts
// src/__tests__/counter.test.ts
import { render, fireEvent } from "@testing-library/vue";
import Counter from "@/components/Counter.vue";
test("increments value on click", async () => {
// The render method returns a collection of utilities to query your component.
const { getByText } = render(Counter);
// getByText returns the first matching node for the provided text, and
// throws an error if no elements match or if more than one match is found.
getByText("Times clicked: 0");
const button = getByText("increment");
// Dispatch a native click event to our button element.
await fireEvent.click(button);
await fireEvent.click(button);
getByText("Times clicked: 2");
});
运行测试用例 npm run test
打开报导文件