vue中如何引入jest單元測(cè)試
一、前言
為什么要搞單元測(cè)試,好處有什么。
- 提測(cè)需要,代碼覆蓋率達(dá)到95%,分支覆蓋率達(dá)到100%,不達(dá)到要求,不給測(cè)。
- 確保代碼正確性。單元測(cè)試可以檢測(cè)和發(fā)現(xiàn)代碼中的錯(cuò)誤,在開(kāi)發(fā)期間及時(shí)糾正。
- 提高代碼質(zhì)量。進(jìn)行單元測(cè)試可以思考更多場(chǎng)景,添加邊界測(cè)試用例,找到更多潛在的問(wèn)題。通過(guò)反復(fù)測(cè)試和修改,代碼的質(zhì)量和可維護(hù)性得到提高。
- 方便重構(gòu)。如果代碼有充分的測(cè)試覆蓋率,重構(gòu)時(shí)就可以更加放心。當(dāng)修改代碼時(shí),運(yùn)行測(cè)試用例可確保沒(méi)有破壞代碼的現(xiàn)有功能)。
- 加速開(kāi)發(fā)流程。單元測(cè)試可以自動(dòng)執(zhí)行,因此可以快速發(fā)現(xiàn)問(wèn)題并且節(jié)省手動(dòng)測(cè)試的時(shí)間,從而加速開(kāi)發(fā)流程。
二、思想
在實(shí)際開(kāi)發(fā)中想清楚vue組件的業(yè)務(wù)代碼和邏輯代碼的處理,把邏輯代碼抽離后編寫(xiě)單元測(cè)試用例再針對(duì)業(yè)務(wù)代碼編寫(xiě)組件測(cè)試用例。
單元測(cè)試
編寫(xiě)單元測(cè)試是為了驗(yàn)證小的、獨(dú)立的代碼單元是否按預(yù)期工作。一個(gè)單元測(cè)試通常覆蓋一個(gè)單個(gè)函數(shù)、類(lèi)、組合式函數(shù)或模塊。單元測(cè)試側(cè)重于邏輯上的正確性,只關(guān)注應(yīng)用整體功能的一小部分。
組件測(cè)試
主要需要關(guān)心組件的公開(kāi)接口而不是內(nèi)部實(shí)現(xiàn)細(xì)節(jié)。對(duì)于大部分的組件來(lái)說(shuō),公開(kāi)接口包括觸發(fā)的事件、prop 和插槽。
當(dāng)進(jìn)行測(cè)試時(shí),測(cè)試這個(gè)組件做了什么,而不是測(cè)試它是怎么做到的。
對(duì)于 視圖 的測(cè)試:根據(jù)輸入 prop 和插槽斷言渲染輸出是否正確。
對(duì)于 交互 的測(cè)試:斷言渲染的更新是否正確或觸發(fā)的事件是否正確地響應(yīng)了用戶(hù)輸入事件。
三、引入
1.新建vue項(xiàng)目直接用腳手架搭建項(xiàng)目時(shí),勾選上單元測(cè)試即可。
2.舊項(xiàng)目添加單元測(cè)試,使用命令:vue add @vue-cli-plugin-unit-jest。
命令執(zhí)行成功后,根目錄下面多了tests文件夾和 jest.config.js 文件,tests文件夾下面有一個(gè)unit文件夾,里面包含了example.spec.js文件;
如下圖所示。
四、使用
1. jest.config文件
module.exports = { // 預(yù)設(shè) preset: '@vue/cli-plugin-unit-jest', // // 多于一個(gè)測(cè)試文件運(yùn)行時(shí)展示每個(gè)測(cè)試用例測(cè)試通過(guò)情況 verbose: true, // // 參數(shù)指定只要有一個(gè)測(cè)試用例沒(méi)有通過(guò),就停止執(zhí)行后面的測(cè)試用例 bail: true, // // 測(cè)試環(huán)境,jsdom 可以在 Node 虛擬瀏覽器環(huán)境運(yùn)行測(cè)試 testEnvironment: 'jsdom', // // 需要檢測(cè)的文件類(lèi)型(不需要配置) moduleFileExtensions: ['js', 'jsx', 'json', 'vue'], // // 預(yù)處理器配置,匹配的文件要經(jīng)過(guò)轉(zhuǎn)譯才能被識(shí)別,否則會(huì)報(bào)錯(cuò)(不需要配置) // transform: { // // 用 `vue-jest` 處理 `*.vue` 文件 // // ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest", // // 用 `babel-jest` 處理 js // "^.+\\.js$": "babel-jest" // }, // // 轉(zhuǎn)譯時(shí)忽略 node_modules // transformIgnorePatterns: ['/node_modules/'], // // 從正則表達(dá)式到模塊名稱(chēng)的映射,和webpack的alisa類(lèi)似(不需要配置) // moduleNameMapper: { // '^@/(.*)$': '<rootDir>/src/$1' // }, // // Jest用于檢測(cè)測(cè)試的文件,可以用正則去匹配 testMatch: [ '**/tests/unit/**/*.spec.[jt]s?(x)', ], // // 是否顯示覆蓋率報(bào)告,開(kāi)啟后顯示代碼覆蓋率詳細(xì)信息,將測(cè)試用例結(jié)果輸出到終端 collectCoverage: true, // // // 告訴 jest 哪些文件需要經(jīng)過(guò)單元測(cè)試測(cè)試 collectCoverageFrom: ["src/assets/js/*.{js,vue}"], // // // 覆蓋率報(bào)告輸出的目錄 coverageDirectory: 'tests/unit/coverage', // // // 報(bào)告的格式 // coverageReporters: ["html", "text-summary"], // // // 需要跳過(guò)覆蓋率信息收集的文件目錄 coveragePathIgnorePatterns: ['/node_modules/'], // // 設(shè)置單元測(cè)試覆蓋率閾值, 如果未達(dá)到閾值,Jest 將返回失敗 coverageThreshold: { global: { statements: 90, // 保證每個(gè)語(yǔ)句都執(zhí)行了 functions: 90, // 保證每個(gè)函數(shù)都調(diào)用了 branches: 90, // 保證每個(gè) if 等分支代碼都執(zhí)行了 lines: 90 }, } }
注意事項(xiàng):
(1)collectCoverageFrom 告訴Jest 哪些文件需要經(jīng)過(guò)單元測(cè)試測(cè)試;
(2)testMatch Jest用于檢測(cè)測(cè)試的文件,可以用正則去匹配;
(3)coverageThreshold 設(shè)置單元測(cè)試覆蓋率閾值, 如果未達(dá)到閾值,影響報(bào)告顏色(雖然你可以自己改)。
2. 測(cè)試用例
export default class Demo { static TimeoutFn (cb) { setTimeout(() => { cb && cb("hello Timeout"); }, 1000) } static promiseFn () { return new Promise(r => { setTimeout(() => { r("hello Promise"); }, 1000) }) } static TimeoutAsnycFn () { return new Promise(r => { setTimeout(() => { r("hello asnyc"); }, 1000) }) } }
demo
import Demo from "@/assets/js/demo.js"; describe("Demo File", () => { it("TimeoutFn", done => { let cb = t => { expect(t).toBe("hello Timeout"); done(); } Demo.TimeoutFn(cb); }) it("promiseFn", () => { return Demo.promiseFn().then(res => { expect(res).toBe("hello Promise") }) }) it("TimeoutAsnycFn", async () => { let res = await Demo.TimeoutAsnycFn(); expect(res).toBe("hello asnyc"); }) })
3. 報(bào)告輸出
- jest.config,js 文件中添加配置項(xiàng) collectCoverage: true;
- package.json 命令行添加 “test:unit”: “vue-cli-service test:unit --coverage”,
- jest.config,js 文件刪除配置項(xiàng) coverageReporters;(添加了終端不會(huì)顯示分支,代碼覆蓋統(tǒng)計(jì)情況)
4.報(bào)告路徑 /tests/unit/coverage/lcov-report/index.html;Statements-代碼,Branches-分支,F(xiàn)unction-函數(shù),Lines-代碼行數(shù)。
4. jest語(yǔ)法
4.1 匹配器(常用,剩下的可以看官網(wǎng))
4.1.1 String,Number 類(lèi)型用 toBe
test("add 1 + 2 to equal 3", () => { expect(1 + 2).toBe(3) }) test("add a + b to equal ab", () => { expect("a" + "b").toBe("ab") })
4.1.2 Array,Object 類(lèi)型用 toEqual
test('Array', () => { expect(["a", "b"]).toEqual(["a", "b"]); }) test('Object', () => { expect({ name: 'xiaoming', age: 18 }).toEqual({ age: 18, name: 'xiaoming' }); })
4.1.3 Boolean,Null, undefined
- toBeNull:判斷是否為null
- toBeUndefined:判斷是否為undefined
- toBeDefined:判斷是否不為undefined
- toBeNaN:判斷是否為NaN
- toBeTruthy:判斷是否為true
- toBeFalsy:判斷是否為false
4.1.4 其他
- toContain:數(shù)組用,檢測(cè)是否包含
- toHaveLength:數(shù)組用,檢測(cè)數(shù)組長(zhǎng)度
4.2 Wrapper
- Wrapper:Wrapper 是一個(gè)包括了一個(gè)掛載組件或 vnode,以及測(cè)試該組件或 vnode 的方法
- Wrapper.vm:這是該 Vue 實(shí)例。你可以通過(guò) wrapper.vm 訪問(wèn)一個(gè)實(shí)例所有的方法和屬性
- Wrapper.classes:返回是否擁有該class的dom或者類(lèi)名數(shù)組
- Wrapper.find:返回第一個(gè)滿(mǎn)足條件的dom
- Wrapper.findAll:返回所有滿(mǎn)足條件的dom
- Wrapper.html:返回html字符串
- Wrapper.text:返回內(nèi)容字符串
- Wrapper.setData:設(shè)置該組件的初始data數(shù)據(jù)
- Wrapper.setProps:設(shè)置該組件的初始props數(shù)據(jù)
- Wrapper.trigger:用來(lái)觸發(fā)事件
4.3 鉤子函數(shù)
- beforeAll 所有測(cè)試用例執(zhí)行之前執(zhí)行
- beforeEach 每個(gè)測(cè)試用例執(zhí)行之前執(zhí)行
- afterEach 每個(gè)測(cè)試用例執(zhí)行完之后執(zhí)行
- afterAll 所有測(cè)試用例執(zhí)行完之后執(zhí)行
使用場(chǎng)景,在測(cè)試接口api時(shí),可以在beforeAll 先調(diào)登錄接口,獲取登錄信息執(zhí)行順序,如下圖所示。
五、問(wèn)題
Q: 執(zhí)行 vue add @vue-cli-plugin-unit-jest 命令報(bào)錯(cuò),如下:
A: 把node版切到16以上即可。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue-manage-system升級(jí)到vue3的開(kāi)發(fā)總結(jié)分析
這篇文章主要為大家介紹了vue-manage-system升級(jí)到vue3的開(kāi)發(fā)總結(jié)分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Vue 刷新當(dāng)前路由的實(shí)現(xiàn)代碼
這篇文章主要介紹了Vue 刷新當(dāng)前路由的實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09Vue?3?表單與后端數(shù)據(jù)交互之查詢(xún)并回顯數(shù)據(jù)步驟流程
本文給大家介紹Vue3表單與后端數(shù)據(jù)交互之查詢(xún)并回顯數(shù)據(jù)步驟流程,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-12-12vue不用window的方式如何刷新當(dāng)前頁(yè)面
這篇文章主要介紹了vue不用window的方式如何刷新當(dāng)前頁(yè)面,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11前端Vue設(shè)置cookie、刪除cookie,獲取cookie方式
這篇文章主要介紹了前端Vue設(shè)置cookie、刪除cookie,獲取cookie方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10Vue+axios使用FormData方式向后端發(fā)送數(shù)據(jù)
在前后端分離的項(xiàng)目中經(jīng)常使用到Vue+axios通過(guò)FormData的方式向后端發(fā)送表單數(shù)據(jù),下面就來(lái)介紹一下如何實(shí)現(xiàn),感興趣的可以了解一下2023-09-09vue使用路由守衛(wèi)實(shí)現(xiàn)菜單的權(quán)限設(shè)置
我們使?vue-element-admin前端框架開(kāi)發(fā)后臺(tái)管理系統(tǒng)時(shí),?般都會(huì)涉及到菜單的權(quán)限控制問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于vue使用路由守衛(wèi)實(shí)現(xiàn)菜單的權(quán)限設(shè)置的相關(guān)資料,需要的朋友可以參考下2023-06-06vue組件中點(diǎn)擊按鈕后修改輸入框的狀態(tài)實(shí)例代碼
要求點(diǎn)擊修改按鈕之后部分輸入框由禁用狀態(tài)變?yōu)榭捎脿顟B(tài)。下面我給大家分享一段實(shí)例代碼基于vue組件中點(diǎn)擊按鈕后修改輸入框的狀態(tài),需要的的朋友參考下2017-04-04