利用vitest实现测试方案

648 阅读3分钟

测试环境

在这里我们选择Vitest来搭建测试 环境。

Vitest 旨在将自己定位为 Vite 项目的首选测试框架,组件工厂是基于Vite构建的项目,在这里我们选择Vitest来作为我们测试框架,为什么会选择vitest 可以查看内容为什么是Vitest

测试工具

测试工具结合Vue的生态,这里我们选择 Vue Test Utilsvue-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 下查看产出结果

示例截图

点击文件可以查看详细的覆盖信息,和未覆盖的代码行。

测试覆盖率的作用

覆盖率反应测试的完整和有效度,通过对结果的分析,新增或者调成测试用例,最求更高的覆盖率。