测试环境
在这里我们选择Vitest来搭建测试 环境。
Vitest 旨在将自己定位为 Vite 项目的首选测试框架,组件工厂是基于Vite构建的项目,在这里我们选择Vitest来作为我们测试框架,为什么会选择vitest 可以查看内容为什么是Vitest。
测试工具
测试工具结合Vue的生态,这里我们选择 Vue Test Utils 和 vue-testing-library 作为测试工具。
如何编写测试用例
组件渲染测试
渲染测试的思路如果组件正常渲染,通过渲染结果的dom 结构,对预期的情况作出评估,检测某个特征值,检测class,检测文本内容,检测dom属性等。
举个🌰;这里有组件,举个例子Input,我们的 在这里,我们截取其中部分做个讲解,代码如下:
import { render, screen, fireEvent } from '@testing-library/vue';
import { expect, test } from 'vitest';
import Component from '@pkg/Input/index.vue'; // 示例代码
test('Input prefix-icon render', async () => {
const { getByText } = render(Component, {
props: {
prefixIcon: 'el-icon-search',
},
});
getByText('addon');
});
渲染结果示意图:
对应的dom结构:
<div class="el-form-item is-success hiddenLabel" field="account" component="proInput" event="account" componentprops="[object Object]">
<label for="account" class="el-form-item__label" style="width: 0px;">输入框:</label>
<div class="el-form-item__content" style="margin-left: 0px;">
<div data-v-d8f73e02="" class="pro-input el-input el-input--suffix" field="account" formdata="[object Object]" component="proInput" placeholder="输入框" suffixtext="addon">
<input type="text" autocomplete="off" field="account" formdata="[object Object]" component="proInput" placeholder="输入框" class="el-input__inner" data-enpassusermodified="yes">
<span class="el-input__suffix"><span class="el-input__suffix-inner"><span data-v-d8f73e02="" class="slot-span">addon</span>
</span><i class="el-input__icon el-input__validateIcon el-icon-circle-check"></i>
</span>
</div>
<!---->
</div>
</div>
在这个case里面我们期望验证 proInput 组件中 suffixText 功能是否正常,思路就是如果组件正常渲染,应该在渲染结果中可以展示找到 addon 的文字内容,如第7行。如果为找到对应的文字 “addon ” 测试用例就会失败。
这里个示例用用到了 @testing-library/vue 和 vitest 两个工具包,具体使用可以参看这两个工具包。
组件事件测试
在vue 组件中,我们需要考虑原生dom事件,vue自定义事件两种事件我们统称为“事件”,当事件触发了就会产生效果,在这里我称他为“副作用”;测试的思路就是,校验当触发了某个事件后,校验副作用是否符合预期。通过下面这个🌰来看看如何完成对两类事件测试。
import { render, screen, fireEvent } from '@testing-library/vue';
import { mount } from '@vue/test-utils';
import { expect, test, describe } from 'vitest';
import Component from '@pkg/proInputPopupEditor/index.vue';
describe('proInputPopupEditor input event', () => {
test(' trigger by code', async () => {
const wrapper = mount(Component, {
props: {
value: 'value-test',
title: 'proInputPopupEditor test',
},
});
wrapper.vm.$emit('input', 'kmui-factory');
expect(wrapper.emitted().input).toBeTruthy();
expect(wrapper.emitted().input[0]).toEqual(['kmui-factory']);
});
test(' trigger by user', async () => {
const { debug, getByText, emitted } = render(Component, {
props: {
value: 'value-test',
title: 'proInputPopupEditor test',
},
});
const btn = getByText('确 定');
await fireEvent.click(btn);
expect(emitted().input[0]).toEqual(['value-test']);
});
});
在上面这个例子我们用了两个工具库@testing-library/vue和 @vue/test-utils可以查阅相关文档。
proInputPopupEditor支持 input 事件,自定义事件通过 emit 来触发,手动触发emit事件,在这里需要用到 @vue/test-utils工具库,检验副作用是否满足预期的代码如下。
wrapper.vm.$emit('input', 'kmui-factory'); // 通过代码逻辑触发 input 事件并加上参数
expect(wrapper.emitted().input).toBeTruthy(); // 在emitted 中校验 input 事件是否触发
expect(wrapper.emitted().input[0]).toEqual(['kmui-factory']); // 在校验参数值
另外一种情况是组件在点击保存的时候也会触发input 事件,通过 fireEvent 来触发原生点击事件。进一步通过emitted 来校验事件的副作用。
const btn = getByText('确 定'); // 获取按钮对象
await fireEvent.click(btn); // 通过 在按钮对象触发 click 事件,注意这里使用 await
expect(emitted().input[0]).toEqual(['value-test']); // 判断
到这里通过两个方式对事件做了校验。
(🌰里的组件不是特别合适,希望表达出校验事件的思路和方法)
组件方法测试
测试覆盖率
测试命令行
npm run test:cover
配置覆盖率
通过vitest 配置了查看测试覆盖率,在配置中支持多重格式查看覆盖率。
coverage: {
reporter: ['text', 'json', 'html'],
},
查看覆盖率结果
运行完后可以在控制台看到如下,这是简版结果,查看更详细的结果可以查看html版本结果
查看html版本结果
运行完测试覆盖率命令后在工程目录 kmui-factory/coverage 下查看产出结果
示例截图
点击文件可以查看详细的覆盖信息,和未覆盖的代码行。
测试覆盖率的作用
覆盖率反应测试的完整和有效度,通过对结果的分析,新增或者调成测试用例,最求更高的覆盖率。