TDesign在vitest的實踐示例詳解
起源
在 tdesign-vue-next
的 CI
流程中,單元測試模塊的執行效率太低,每次在單元測試這個環節都需要花費 6m
以上。加上依賴按照,lint
檢查等環節,需要花費 8m
以上。
加上之前在單元測試這一塊隻是簡單的處理瞭一下,對開發者提交的組件也沒有相應的要求,隻是讓它能跑起來就好。另一方面單元測試目前是 TD 發佈正式版的一個卡點,所以準備對其進行一次梳理和重構,為後續的重點工作做準備。
痛點與現狀
- 單元測試執行效率太低,上面已經講到瞭,這個速度是無法忍受。
- 單元測試規范不明確,開發者沒有對應的單測規范可以遵循,不知道怎麼寫。
- 單元測試中
snapshot
占據瞭大多數,每個組件的單元測試中其所有demo
都做瞭一次snapshot
。這部分的代碼由腳本輸出。在一定程度上屬於集成測試,但執行過程融合在人工寫的單元測試當中,需要做集成測試的整合。
vitest
最開始註意到 vitest
是在 evan you
的分享裡面。vitest
的特性如下:
- 與
Vite
的配置、轉換器、解析器和插件通用,免去瞭額外對jest
的配置 - 對
TypeScript / JSX
支持開箱即用的,像寫組件一樣寫測試 - 多線程通過
tinypool
使用Worker
線程盡可能多地並發運行測試。隔離瞭每個測試文件的運行環境,因此一個文件中的運行環境改變不會影響其他文件。 watch
模式下極速熱更,在單元測試開發時更友好- 與
Jest
幾乎相同的API
,極少量的差異 - 更清晰的
C8
生成測試覆蓋率 - 源碼內聯測試
- 非常酷的
GUI
遷移
配置文件改造
依賴,上面說到,vitest
的配置文件和 vite
的配置文件共用,且插件也是共用,所以不需要像配置 jest
一樣去配置 babel-jest
, vue-jest
, jest-serializer-vue
這些插件。
開發環境
vitest
中開發環境的執行命令
vitest --config site/vite.config.js
單測開發的過程中,需要過濾對應的測試文件,則隻需要加上對應的文件路徑即可,具體如下:
#執行button組件的單測 vitest --config site/vite.config.js button #執行button的index.test.jsx測試文件 vitest --config site/vite.config.js button/index.test.jsx
另外還有 GUI
的選項
vitest --config site/vite.config.js --ui
集成測試
之前我們繼承測試環境有兩套 ssr
環境和 csr
環境。
ssr 環境
對 ssr
環境的測試需要做一個 setup
用來做組件 render
,此部分和之前保持一致。
ssr-setup
import { config } from '@vue/test-utils'; import { createApp } from 'vue'; import { renderToString } from '@vue/server-renderer'; import TDesign from '@/src/index'; config.global.plugins = [TDesign]; // global掛載createSSRApp方法,掛載render環境的配置 config.global.createSSRApp = (comp) => { const app = createApp(comp); app.config.globalProperties.$route = {}; app.use(TDesign); const html = renderToString(app); return html; };
之前的執行環境是 commonjs
引入組件使用的是 require
, 在 vite
中需要替換為 es
規范的 import
const demo = require(`../.${file}`);
ssr.test.js
import glob from 'glob'; import MockDate from 'mockdate'; import { config } from '@vue/test-utils'; MockDate.set('2020-12-28 00:00:00'); function runTest() { const files = glob.sync('./examples/**/demos/*.vue'); const { createSSRApp } = config.global; describe('ssr snapshot test', () => { files.forEach((file) => { it(`ssr test ${file}`, async () => { const demo = await import(`../.${file}`); //此部分 const realDemoComp = demo.default ? demo.default : demo; const html = await createSSRApp(realDemoComp); expect(html).toMatchSnapshot(); }); }); }); } runTest();
csr 環境
csr
環境的集成測試在之前使用的是腳本輸出一個如下的標準文件,分散在每個組件的單元測試裡面。這樣做影響單元測試的執行效率,對每個組件都開一個 describe
, 這些代碼會影響單元測試的代碼結構。所以合並在一個文件執行是最合理的。其實現思路與ssr
基本一致,隻是 render
不一樣而已。
/** * 該文件為由腳本 `npm run test:demo` 自動生成,如需修改,執行腳本命令即可。請勿手寫直接修改,否則會被覆蓋 */ import { mount } from '@vue/test-utils'; import baseVue from '@/examples/affix/demos/base.vue'; import containerVue from '@/examples/affix/demos/container.vue'; const mapper = { baseVue, containerVue, }; describe('Affix', () => { Object.keys(mapper).forEach((demoName) => { it(`Affix ${demoName} demo works fine`, () => { const wrapper = mount(mapper[demoName]); expect(wrapper.element).toMatchSnapshot(); }); }); });
csr.test.js
import glob from 'glob'; import MockDate from 'mockdate'; import { mount } from '@vue/test-utils'; MockDate.set('2020-12-28 00:00:00'); function runTest() { const files = glob.sync('./examples/**/demos/*.vue'); describe('csr snapshot test', () => { files.forEach((file) => { it(`csr test ${file}`, async () => { const demo = await import(`../.${file}`); const realDemoComp = demo.default ? demo.default : demo; realDemoComp.name = `test-csr-${realDemoComp.name}`; const wrapper = mount(realDemoComp); expect(wrapper.element).toMatchSnapshot(); }); }); }); } runTest();
配置文件
vitest
的配置文件如下,下面這一段 config
隻需要掛在 vite.config.js
的 test
選項即可.
const testConfig = { include: process.env.NODE_ENV === 'test-snap' ? ['test/snap/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'] : ['test/unit/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], globals: true, environment: 'jsdom', testTimeout: 5000, setupFiles: process.env.NODE_ENV === 'test-snap' ? path.resolve(__dirname, '../script/test/test-setup.js') : '', transformMode: { web: [/\.[jt]sx$/], }, coverage: { reporter: ['text', 'json', 'html'], }, };
兼容性
因為我們老的測試方案基於 jest
,相應的 API
都有。所以在遷移過程中,兼容性問題基隻有一些從 jest
中的函數,切換到 vi
,其他問題沒有遇到。
before
const fn = jest.fn();
after
import { vi } from 'vitest'; const fn = vi.fn();
結果
CI測試速度提升
在 CI
中從原來的 6m
提升到 2m30
, 執行效率提升百分之 60%
,在開發機的執行效率更高(不同配置的機器執行效率不同,用 ci
中的標準執行做對比測試)。
更清爽的日志信息
jest
這一部分的 log
隻是單個組件的日志,而整個 log
記下來是非常長的,導致我們在開發中會忽略掉很多日志的告警。本地的 terminal
輸出的長度是有限制的。而 vitest
的 log
則非常清爽。
源碼傳送門
以上就是TDesign在vitest的實踐示例詳解的詳細內容,更多關於TDesign在vitest實踐的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- vue中如何使用jest單元測試
- vue3+vite2中使用svg的方法詳解(親測可用)
- 使用vue3.x+vite+element-ui+vue-router+vuex+axios搭建項目
- 使用vite創建vue3項目的詳細圖文教程
- vue3如何按需加載第三方組件庫詳解