# Vue單元測試學習筆記 在深入技術前,可以先閱讀Vue官方的[測試建議](https://cn.vuejs.org/guide/scaling-up/testing.html) 以下,會介紹幾個在專案中撰寫測試搭配的套件及其初始範例,詳細寫法還請參考個別的官方文件。 ## Unit-jest (Jest & Vue Test Utils) ### About >[jest](https://jestjs.io/docs/getting-started) 官方文件 Jest 是一個由Facebook 開發的 test runner,它提供許多豐富的功能,例如:斷言、分析測試涵蓋率、 mock 功能與良好的錯誤提示訊息等。 Jest 可以測試的範圍涵蓋了 JavaScript 相關的技術,包含後端的 Node.js 與前端的 Vue 、 Angular 或 React ,是個完善的測試框架。 > Vue Test Utils [英文](https://v1.test-utils.vuejs.org/guides/#getting-started) / [中文](https://v1.test-utils.vuejs.org/zh/guides/#%E8%B5%B7%E6%AD%A5)官方文件 > Vue Test Utils 是Vue.js 官方所維護的單元測試套件,它提供了一系列的API 使我們很容易去操作存取元件 #### 建立含有單元測試的專案 ``` $ vue create vue-test -m npm Vue CLI v5.0.8 ? Please pick a preset: Manually select features ? Check the features needed for your project: Babel, Unit ? Choose a version of Vue.js that you want to start the project with 2.x ? Pick a unit testing solution: Jest ... ``` 它會直接幫你建立測試的範例檔 ![](https://i.imgur.com/rDuBIgr.png) 運行後可以得到 ```shell $ npm run test:unit ``` ![](https://i.imgur.com/OEzUPEh.png) #### 於現有專案安裝 ```shell $ vue add unit-jest ``` ### 簡單範例:Counter 1. 建立一個counter頁面,點擊按鈕後數字會+1 `@/components/Counter.vue` ```javascript= <template> <div> <h1>Count: {{ count }}</h1> <button id="increment-btn" @click="count++"> +1 </button> </div> </template> <script> export default { data() { return { count: 0, } }, } </script> ``` 會長得像這樣: ![](https://i.imgur.com/DFkmlA0.png) 2. 寫測試 預期初始值會是0,點擊一下之後會變成1 `tests/unit/counter.spec.js` ```javascript= import { mount } from '@vue/test-utils' import Counter from '@/components/Counter.vue' describe('Counter.vue', () => { it('click once', async () => { // 驗證初始值 const wrapper = mount(Counter) expect(wrapper.vm.count).toBe(0) // 獲取元件 const button = wrapper.find('button') const h1 = wrapper.find('h1') // 測試互動 await button.trigger('click') expect(h1.text()).toContain('1') }) }) ``` 3. 結果 ![](https://i.imgur.com/pVk6LeT.png) ## Vitest * Vitest 与大多数 Jest API 和生态系统库都有较好的兼容性,可以無痛轉換 * 如果專案本身由 Vite 驅動,推薦以 Vitest 作為測試工具 * 寫測試時也可以搭配 Vue Test Utils 或 testing-library 做組件測試使用 ### Install 基本上用 `vue-create` 建專案的話都會內建,沒有的話可以用下列指令安裝 ```shell $ npm install -D vitest $ npm i @vitejs/plugin-vue ``` 建立設定檔 `vitest.config.ts` ```javascript= import { fileURLToPath, URL } from "node:url" import { defineConfig } from "vite" import type { UserConfig as VitestUserConfigInterface } from "vitest/config" import vue from "@vitejs/plugin-vue" const vitestConfig: VitestUserConfigInterface = { test: { globals: true, environment: "jsdom", // 也可以用happy-dom之類的 }, } export default defineConfig({ plugins: [vue()], resolve: { alias: { "@": fileURLToPath(new URL("./src", import.meta.url)), }, }, test: vitestConfig.test, }) ``` 配置 `package.json` ```javascript "scripts": { "test": "vitest", "coverage": "vitest --coverage" // 稍後覆蓋率會用到 }, ``` > 配置方式參考 > [vue 官方建議](https://vuejs.org/guide/scaling-up/testing.html#recipes) > [一篇來自 stackoverflow 的建議](https://stackoverflow.com/questions/70769062/vue-test-utils-for-vue3-document-is-not-defined) ### 簡單範例(搭配Vue Test Utils) 要先安裝 Vue Test Utils ``` $ npm install @vue/test-utils --save-dev ``` 建立基本測試,檔名須遵照 `xxx.test.js` 規則 code和上面jest的寫法一樣 `@/tests/example.test.js` ```javascript= import { mount } from "@vue/test-utils"; import HelloWorld from "@/components/HelloWorld.vue"; import { describe, expect, test } from "vitest"; describe('HelloWorld.vue', () => { test('renders props.msg when passed', () => { const msg = 'new message' const wrapper = mount(HelloWorld, { propsData: { msg } // Mocking Props }) expect(wrapper.text()).toMatch(msg) }) }) ``` 運行測試,本指令會自動 watch ```shell $ npm test ``` ![](https://i.imgur.com/C53iNpq.png) ### 覆蓋率 > [官方文件](https://vitest.dev/guide/coverage.html) 設定 `vitest.config.ts` ```javascript const vitestConfig: VitestUserConfigInterface = { test: { globals: true, environment: "jsdom", /* 新增以下設定 */ coverage:{ all: true, provider: 'c8', // 也可以用istanbul reporter: ['text', 'json', 'html'], }, include: ['**/tests/*.js'], // 測試檔案路徑,也可以不設定預設抓所有 /* ---------- */ }, } ... ``` 安裝覆蓋率套件 ```shell $ npm i -D @vitest/coverage-c8@{你的vitest版本號} ``` 運行指令 ```shell $ npm run coverage ``` * 從terminal檢視 ![](https://i.imgur.com/5MuEuG3.png) * 檢視網頁介面報告 運行覆蓋率指令後,會自動生成 `/converage` 資料夾 ![](https://i.imgur.com/wRRErBE.png) 打開html網頁後,可以查看詳細的報告 ![](https://i.imgur.com/CuOrmFC.png) ## testing-library >[testing-library](https://testing-library.com/docs/) 官方文件 ```shell $ npm install --save-dev @testing-library/vue ``` ## 語法指令 ### Vue Test Utils > [Vue Test Utils APIs](https://v1.test-utils.vuejs.org/zh/api/#api) ### Vitest > [vitest APIs](https://cn.vitest.dev/api/) Jest 的指令基本上和 Vitest 是兼容的 ### Jest > [jest APIs](https://jestjs.io/docs/api) ## 其他 ### Cypress ## 參考資料 [尋覓網站開發的神兵利器系列 第 38 篇 Extra07 - Jest - 單元測試框架](https://ithelp.ithome.com.tw/articles/10282152)