NutUI 单元测试:从 jest 到 vitest

2207 篇文章 2 订阅
2073 篇文章 14 订阅

2024软件测试面试刷题,这个小程序(永久刷题),靠它快速找到工作了!(刷题APP的天花板)_软件测试刷题小程序-CSDN博客文章浏览阅读3.4k次,点赞86次,收藏15次。你知不知道有这么一个软件测试面试的刷题小程序。里面包含了面试常问的软件测试基础题,web自动化测试、app自动化测试、接口测试、性能测试、自动化测试、安全测试及一些常问到的人力资源题目。最主要的是他还收集了像阿里、华为这样的大厂面试真题,还有互动交流板块……_软件测试刷题小程序​编辑https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502​编辑https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502​编辑https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502​编辑https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502​编辑https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502​编辑https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502​编辑https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502​编辑https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502icon-default.png?t=N7T8https://blog.csdn.net/AI_Green/article/details/134931243?spm=1001.2014.3001.5502

NutUI Vue 自 3.0 版本起,开始使用 vite 作为项目的构建工具,单元测试工具则依然使用 jest。而后 vite 官方团队开源了 vitest 作为 vite 的首选测试框架和 jest 的替代品。

本文主要介绍 NutUI 从 jest 到 vitest 的迁移过程,以及后续对于单元测试流程的改造升级。

一、时间线

  • 1、2023.04,NutUI 从 jest 迁移到 vitest,此时使用初期的 0.29.8 版本
    • 总计480 组单元测试
    • 迁移前后,单测运行总时间从 120s 下降为 48s
  • 2、2023.12,vitest 正式发布了 1.0.0 版本
  • 3、2024.01,测试环境从 jsdom 迁移到 happy-dom
    • 迁移前后,单测运行总时间从 40s 下降为 30s

二、从 jest 到 vitest 的流程

NutUI 仓库从 jest 到 vitest 的迁移源码参考:jdf2e/nutui#2217

下面将依次介绍完整的迁移流程:

1、包依赖变更

jest 默认仅支持处理 JS 文件,需要使用 ts-jest 插件或者使用 babel 预处理以支持 TS,对于 vue 组件则需要使用 vue-jest 插件做额外的转换。而这些对于 vitest 来说都不需要,它将这些复杂的流程交给 vite 处理。

jest 与 vitest 内部默认均使用 jsdom,它可以支持 canvas 的相关接口,需要依赖 canvas 包。很不幸,这个 node-canvas 包的安装过程就和 node-sass 一样痛苦。我们选择 jest-canvas-mock 以及基于它封装的 vitest-canvas-mock 插件做替代,它们的依赖更干净。

jest 插件vitest 插件备注
jest替换为 vitest
ts-jest移除
vue-jest移除
@types/jest移除
jest-canvas-mock替换为 vitest-canvas-mock
新增 @vitest/uivitest 的 UI 界面
新增 @vitest-coverage-c8vitest 测试覆盖率工具

2、配置修改

jest 的配置文件:

// jest.config.cjs
module.exports = {
  moduleFileExtensions: ['vue', 'js', 'ts', 'tsx'],
  preset: 'ts-jest',
  testEnvironment: 'jsdom', // 测试环境
  // 配置不同文件的处理逻辑
  transform: {
    '^.+\\.vue$': 'vue-jest', // vue 文件用 vue-jest 转换
    '^.+\\.ts$': 'ts-jest' // ts 文件用 ts-jest 转换
  },
  // 匹配 __tests__ 目录下的 .js/.ts 文件 或其他目录下的 xx.test.js/ts xx.spec.js/ts
  testRegex: '(/__tests__/*|(\\.|/)(test|spec))\\.(ts|tsx)$',
  //testRegex: '__tests__.action.spec.ts',
  // alias 配置
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1'
  },
  // 是否开启将测试覆盖率信息输出为报告
  collectCoverage: true,
  // 覆盖率报告涉及哪些文件
  collectCoverageFrom: [
    'src/packages/__VUE/**/*.{js,jsx,ts,tsx,vue}',
    '!**/node_modules/**',
    '!**/demo.vue/**',
    '!**/index.taro.vue/**'
  ]
};

vitest 的配置则更简洁一些,因为它可以复用 vite 的配置项,包括但不限于 alias、插件系统、css 处理逻辑等等。

只需要在已有的 vite.config.ts 文件中做以下调整:

/// <reference types="vitest" />
// 增加上面这行注释标记后,项目中的 vitest 将以当前文件作为配置文件

export default defineConfig({
  // 这里是原项目中的 vite 配置
  ...
  // 下面是新增的 vitest 的配置
  test: {
    globals: true, // 是否开启 vitest 的全局变量注入
    environment: 'jsdom', // 测试环境,默认 jsdom,可选项 happy-dom
    coverage: {
      all: false,  // 覆盖率报告是否以所有文件作为基准。不开启时,会将所有测试用例关联到的文件作为基准。
      provider: 'c8'  // 测试覆盖率工具。在 vitest 的后续版本中将升级为 v8
    },
    // 匹配所有的测试用例文件
    include: ['src/packages/__VUE/**/*.(test|spec).(ts|tsx)'],
    // 输出测试报告的格式
    reporters: ['default', 'html']
  }
});

3、测试用例

vitest 的 API 设计几乎保持了与 jest 一致,测试用例的修改步骤很简单,只需要一些批量替换操作,就可以运行起来。

  • 全局变量 jest 需要批量替换为 vi
    • jest.mock --> vi.mock
    • jest.fn --> vi.fn
  • 测试快照:运行 vitest 更新所有快照文件
    • 快照文件的签名从 jest 变为 vitest
    • 组件快照变得更加简洁直观,不再包含多余的转义符 参考这个 PR

经过以上三个步骤,就已经完成了从 jest 到 vitest 的迁移。

4、迁移效果

vitest 具有以下优势:

  • 1、速度更快:整个测试流程从 120s 下降到了 48s
  • 2、UI 界面:通过 @vitest/ui 可以在单测运行时启动一个网页,展示所有的测试用例运行情况、模块之间的关联图,搭配 vscode 插件后可以在源码中标出具体出错的代码行。
  • 3、HMR:从未有过的体验,单元测试也可以做到热更新。
  • 4、原生支持 ESM、TS 等等:jest 似乎至今仍未默认支持 ESM 模块,而大多数框架已经开始逐渐淘汰 CJS 了。

对于一个 vite 项目,使用 vitest 的配置会更加简单,本质原因在于它与 Vite 使用了一致的配置、转换器、解析器和插件。对于代码的转换流程,可以直接使用项目中已有的 vite 插件进行处理。而在 vite 项目中使用 jest 就相当于对同一个处理逻辑配置了两套完全不同的处理逻辑,配置繁琐,运行效率低。

三、迁移后的建设

在迁移到 vitest 之后,我们对测试流程又做了一些改进工作。

1、接入 codecov

在每一次 PR/Push 时,执行 vitest 测试流程,输出单测覆盖率报告并上传至 codecov 网站,这里可以看到 NutUI 项目单测覆盖率的完整数据:codecov/jdf2e/nutui

2、使用 TSX 编写测试用例

在以往使用 jest + vue-test-utils 时,编写 vue 组件的测试用例通常会使用以下两种方式:

方式一:渲染函数
// test.ts
import { mount } from '@vue/test-utils';
import Button from '../index.vue';

test('Button', async () => {
  const wrapper = mount(Button, {
    props: {},
    slots: {},
    // ...
  });
  const btn = wrapper.find('.nut-button');
  // 断言 ...
});

在 vue 中使用渲染函数编写组件是一件很痛苦的事情,对于大量使用插槽的复杂组件尤其麻烦。这种方式只适合编写简单组件的测试用例。

方式二:模板语法
// test.ts
import { mount } from '@vue/test-utils';
import { ref } from 'vue';
import Button from '../index.vue';

test('Button', async () => {
  const wrapper = mount({
    template: `
      <template>
        <nut-button @click="onClick"> {{ count }} </nut-button>
      </template>
    `,
    setup() {
      const count = ref(0);
      const onClick = () => {
        count.value++;
      };
      return { onClick };
    }
  });
  // 断言 ...
});

这种方式用纯字符串的方式编写 vue 模板,不再需要繁杂的渲染函数,整体代码风格为选项式 defineComponent + setup 函数的形式。

它存在一个更严重的问题,vue 模板丢失了 TS 类型校验,并且选项式 setup 的风格依然存在大量冗余代码。

方式三:TSX

在切换到 vitest 之后,我们很容易获得了第三种方式。只需要在 vite 配置中增加 @vitejs/plugin-vue-jsx 即可。

想象一下在 jest 框架下,如何支持 tsx 格式的单测用例呢?

vue-jest 并不支持,我们可能需要一个 vue-jsx-jest 插件(它并不存在)去做这层转换,或者手动引入 @vue/babel-plugin-jsx 插件进行处理。

// test.tsx
import { mount } from '@vue/test-utils';
import { ref } from 'vue';
import Button from '../index.vue';

test('Button', async () => {
  const count = ref(0);
  const onClick = () => {
    count.value++;
  };
  const wrapper = mount(() => {
    return (
      <Button onClick={onClick}> {{ count }} </Button>
    );
  });
  // 断言 ...
});

虽然 vue 主推的代码风格为 SFC + script setup,但是单元测试本身需要使用 js/ts 编写,如果引入外部的 .vue 文件也会变得繁琐。笔者认为 tsx 是当前最合适的 vue 组件单测用例代码风格。

3、测试环境从 jsdom 到 happy-dom

迁移源码参考:jdf2e/nutui#2881

jest 和 vitest 的默认测试环境均为 jsdom,它是一个比较成熟的、主流的方案,而 happy-dom 是一个新的挑战者。它迭代更频繁,对于新特性的支持更迅速。

计划从 jsdom 切换到 happy-dom 的念头来自这样一个简单的例子:

某个组件中使用了 css 样式 background-origin: border-box,在 jest 测试中不能被识别。原因在于 jsdom 使用 jsdom/cssstyle 进行 css 相关的处理,这里并没有发现这个样式的识别逻辑。

从 jsdom 切换到 happy-dom 之后,主要产生了以下影响:

  • 1、对于颜色的处理逻辑,jsdom 会转换为 16 进制颜色,而 happy-dom 则保持原始值
  • 2、happy-dom 可识别的 HTML、CSS 属性更丰富
  • 3、单测快照文件与行覆盖率未产生明显变化(<1%)
  • 4、运行速度进一步加快,单测 CI 流程时间从 40s 下降到 30s

四、最后

感谢阅读,文中可能存在不准确或错误之处,如果您发现任何问题,欢迎指正,非常感激。

NutUI GitHub 仓库:

NutUI 官网:nutui.jd.com

 

行动吧,在路上总比一直观望的要好,未来的你肯定会感谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入群: 759968159,里面有各种测试开发资料和技术可以一起交流哦。

最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

​​​软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

在这里插入图片描述

在这里插入图片描述

  • 20
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值