Vitest是啥?
Vitest是去年由Vue团队出品的最新的测试框架,由于有Vite的支持,开发体验上几乎是顶级的,开发使用上面,Vitest几乎复制了一份Jest的API,支持了Jest拥有的功能且支持在浏览器运行,因此迁移起来成本不大。
在Vite项目中可以直接公用原有的项目配置(vite.config.js),在React中使用的配置也不麻烦。
缺点是目前还只是0.x.x版本,部分功能还有一些小bug,社区使用度还很低,迁移过程中的报错信息也不太友好,不过相信解决都只是时间的问题。
迁移后的效果
迁移到vitest主要是为了快,快就是王道,具体效果有多快?
Vitest跑全部测试:1.96s
Jest跑全部测试:9.415s
Jest跑单个测试:3.141s
Vite跑单个测试:1.64s
我的配置(太长不看?直接抄配置)
笔者的项目是React + Vitest + Testing Library技术栈,省时间可以直接抄配置。
// src/setupTests.ts
import '@testing-library/jest-dom'; //用来import RTL扩展的断言api
// vite.config.js
/// <reference types="vitest" />
/// <reference types="vite/client" />
import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react'
import svgrPlugin from 'vite-plugin-svgr'
export default defineConfig({
plugins: [
react(),
svgrPlugin({ svgrOptions: { icon: true } })
],
test: {
globals: true,
setupFiles: 'src/setupTests.tsx',
environment: "jsdom",
exclude: ["src/__visual_tests__", '**/node_modules/**', '**/dist/**', '**/cypress/**', '**/.{idea,git,cache,output,temp}/**']
},
})
官方指南
- Getting Started cn.vitest.dev/guide
- 迁移指南 cn.vitest.dev/guide/migra…
自己踩的坑
1. Typescript对全局API的支持
Jest默认使用全局API(describe,jest,it等),通过配置,vite也能支持全局api,但是在TS项目中我们还需要配置一下tsconfig.json来确保静态检查不会报错:
// tsconfig.json
{ "compilerOptions": { "types": ["vitest/globals"] } }
2. document is not defined
vite的默认运行环境的node,对于UI的dom测试,我们需要手动配置运行环境为jsdom,才能正常使用浏览器的api:
import { defineConfig } from 'vitest/config';
export default defineConfig({ test: { environment: "jsdom", }, })
3. Invalid Chai property
toBeInTheDocument并非Chai的api,这个报错信息着实是有些迷惑,实际上toBeInTheDocument是RTL的api,这里报错是因为没有在setupTests中import RTL的jest-dom:
// vite.config.js
// ...
export default defineConfig({ test: { setupFiles: 'src/setupTests.tsx', }, })
// src/setupTests.tsx
import '@testing-library/jest-dom';
4. jest is not defined
如果项目中原本有使用到全局对象jest的方法,比如jest.fn()jest.mock()等,运行测试时会报错,这个很自然,毕竟你已经迁移到jest了,jest全局对象当然是不能用了,这块其实vitest基本都兼容了jest用到的api了,你仅需把jest.批量替换为vi.,并确保全局api配置已经开启即可:
// vite.config.js // ...
export default defineConfig({ test: { globals: true, }, })
// xxx.test.tsx
// jest.mock(...)
// 修改为
vi.mock(...)
// jest.fn(...)
// 修改为
vi.fn(...)
5. react is not defined;Unable to fire a "click" event - please provide a DOM element.
如果你测试的是react组件,使用了svgr等,你可能还需要配置一些vite plugins来支持运行时不报错:
// vite.config.js // ... import { defineConfig } from 'vitest/config';
import react from '@vitejs/plugin-react'
import svgrPlugin from 'vite-plugin-svgr'
export default defineConfig({
plugins: [
react(),
svgrPlugin({ svgrOptions: { icon: true } })
],
});
6. mock es模块
使用jesk.mock来mock es模块时,默认能mock模块里面的default返回。
// setupTests.ts
vi.mock('@scope/icon', () => {
return function Icon(props: IconProps) {
return <div data-testid="testIcon">{props.type}</div>;
};
});
然而直接把jest改成vi之后,就会出现一些奇怪的react报错:
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
表示你import了一个undefined用来当成react组件来渲染。
解决办法:需要手动mock esm的 default export
// setupTests.ts
vi.mock('@mail/ui.icon', () => {
return {
default: function Icon(props: IconProps) {
return <div data-testid="testIcon">{props.type}</div>;
},
};
});