如何為vue的項目添加單元測試
動機
- 單元測試能避免出現(xiàn)一些代碼運行結果與預期不符的錯誤,通常是一些比較低級但又難以發(fā)現(xiàn)的問題。
- 粗心且懶,在每次調整之后,需要不斷地檢查代碼,反復去走流程。擔心由于自己的改動而導致了邏輯上的錯誤。而這里面的一大部分工作其實可以讓單元測試來完成。
- 有了單元測試之后,可以對代碼本身形成一種規(guī)范。如果在進行單元測試過程中發(fā)現(xiàn)自己的一些代碼不方便進行測試,那么你可能需要重新審視這些代碼,看是否有一些設計上不合理或者可以優(yōu)化的地方。
- 嵌入了單元測試的項目顯得更加的專業(yè),也會更有逼格,測試本身是開發(fā)環(huán)節(jié)需要做的內容。
工具選取對比(一個合適測試框架 -- Jest)
之前也沒有去接觸過前端的單元測試,也是這幾天開始了解,開始并沒有頭緒,所以就在網(wǎng)上以及github上去看了一些之前比較流行的測試框架。發(fā)現(xiàn)比較流行的是karma + mocha + Chrome的組合。當我單獨一個個去看的時候,發(fā)現(xiàn)其內容還是比較的多的。之后選取了jest也是經過對比權衡的
優(yōu)點
1、一站式的解決方案,學習成本更低,上手更快(很適合現(xiàn)如今我的需求)
在使用 Jest 之前,我需要一個測試框架(mocha),需要一個測試運行器(karma),需要一個斷言庫(chai),需要一個用來做 spies/stubs/mocks 的工具(sinon 以及 sinon-chai 插件),一個用于測試的瀏覽器環(huán)境(可以是 Chrome 瀏覽器,也可以用 PhantomJS)。 而使用 Jest 后,只要安裝它,全都搞定了。
2、全面的官方文檔,易于學習和使用
Jest 的官方文檔很完善,對著文檔很快就能上手。而在之前,我需要學習好幾個插件的用法,至少得知道 mocha 用處和原理吧 我得學會 karma 的配置和命令,chai 的各種斷言方法……,經常得周旋于不同的文檔站之間,其實是件很煩也很低效的事
3、更直觀明確的測試信息提示
4、方便的命令行工具
缺點
jsdom 的一些局限性:因為 Jest 是基于 jsdom 的,jsdom 畢竟不是真實的瀏覽器環(huán)境,它在測試過程中其實并不真正的“渲染”組件。這會導致一些問題,例如,如果組件代碼中有一些根據(jù)實際渲染后的屬性值進行計算(比如元素的 clientWidth)就可能出問題,因為 jsdom 中這些參數(shù)通常默認是 0.
綜上所述,最終我確定下來的方案是使用成熟好用的測試工具庫 --- vue-test-utils 其前身是 avoriaz,avoriaz 也是一個不錯的包,但其 README 中有說明,當 vue-test-utils 正式發(fā)布的時候, 它將會被廢棄。 vue-test-utils 能極大地簡化 Vue.js 單元測試。 例如:Vue 單元測試,一般是像下面這樣的(包括 vue-cli 提供的模板里默認也是這樣):
import Vue from 'vue' import HelloWorld from '@/components/HelloWorld' describe('HelloWorld.vue', () => { it('should render correct contents', () => { const Constructor = Vue.extend(HelloWorld) const vm = new Constructor().$mount() expect(vm.$el.querySelector('.hello h1').textContent) .toEqual('Welcome to Your Vue.js App') }) })
使用 vue-test-utils 后,你可以像下面這樣
import { shallow } from '@vue/test-utils' import HelloWorld from '@/components/HelloWorld' describe('HelloWorld.vue', () => { it('should render correct contents', () => { const wrapper = shallow(HelloWorld, { attachToDocument: ture }) expect(wrapper.find('.hello h1').text()).to.equal('Welcome to Your Vue.js App') }) })
可以看到代碼更加簡潔了。wrapper 內含許多有用的方法,上面的例子中所使用的 find() 其中最簡單不過的一個。vue-test-utils 還有 createLocalVue() 等方法以及 stub 之類的功能,基本上可以完成絕大部分情況下的測試用例,這也是非常的實用的了。
安裝使用
安裝使用的方式很簡單,由于想引入到現(xiàn)有的項目中來,現(xiàn)有的項目大多是vue-cli創(chuàng)建的,所以一開始的時候基本上是已經安裝并配置好了 webpack、vue-loader 和 Babel。如果是比較原始的項目,也是可以單獨安裝的。
我們要做的第一件事就是安裝 Jest 和 Vue Test Utils:
$ npm install --save-dev jest @vue/test-utils
然后我們需要在 package.json 中定義一個單元測試的腳本。
// package.json { "scripts": { "test": "jest" } }
在 Jest 中處理單文件組件
npm install --save-dev vue-jest
接下來在 package.json 中創(chuàng)建一個 jest 塊:
{ // ... "jest": { "moduleFileExtensions": [ "js", "json", // 告訴 Jest 處理 `*.vue` 文件 "vue" ], "transform": { // 用 `vue-jest` 處理 `*.vue` 文件 ".*\\.(vue)$": "vue-jest" } } }
具體的使用步驟
此處我根據(jù)自己的需求來進行整理
對頁面內容的測試
// viewTest.vue <template> <div class="hello"> <h1>{{ msg }}</h1> <p>1212121</p> </div> </template> <script> export default { name: 'viewTest', data () { return { msg: 'Welcome to Your Vue.js App' } } }
// viewTest.spec import { mount } from '@vue/test-utils' import Component from '../../../src/components/viewTest' describe('頁面展示測試', () => { test('檢查元素是否存在', () => { const wrapper = mount(Component) expect(wrapper.contains('.hello h1')).toBe(true) console.log(wrapper.find('.hello h1').text()) expect(wrapper.text()).toContain('Welcome') }) })
這個是最簡單的對頁面的dom節(jié)點的測試,以及可以對文案進行一些測試,這些是比較基礎的
對事件處理的測試
// event.vue <template> <div> <h1>My To Do event</h1> <h2>wawawawawawa</h2> <input v-model="newItem"> <button @click="addItemToList">Add</button> </br> <!--displays event --> <ul> <li v-for="item in listItems">{{ item }}</li> </ul> </div> </template> <script> export default { name: 'event', data () { return { listItems: ['buy food', 'play games', 'sleep'], newItem: '' } }, methods: { addItemToList() { this.listItems.push(this.newItem); this.newItem = ''; } } } </script>
// event.spec.js // 從測試實用工具集中導入 `mount()` 方法 // 同時導入你要測試的組件 import { mount } from '@vue/test-utils' import Component from '../../../src/components/itemEvent' describe('事件觸發(fā)測試', () => { test('事件觸發(fā)測試', () => { // 現(xiàn)在掛載組件,你便得到了這個包裹器 const wrapper = mount(Component) const button = wrapper.find('button') wrapper.setData({ newItem: '添加測試項', }) button.trigger('click') console.log(wrapper.text()) expect(wrapper.text()).toContain('添加測試項') }) })
這里是在模擬用戶交互的一個測試,當用戶點擊按鈕的時候會把數(shù)據(jù)插入到當前的列表中來,所以最開始需要定位到這個按鈕,可以用find(),之后要去觸發(fā)這個事件, button.trigger('click'),然后把預期的結果,與按照流程的結果相比較,以達到測試的效果。這里模擬的是一個點擊事件,當然,api也支持各種的鼠標事件以及鍵盤事件。
測試異步行為 平時的業(yè)務場景中肯定是離不開異步操作的,當發(fā)送一個接口請求的時候應該怎么去才做。Jest 運行測試用例同時可以模擬了 HTTP 庫 axios,對預期結果可以進行設定和比較,比如:
// axios.js export default { get: () => Promise.resolve({ data: 'response' }) }
<template> <div> <button @click="fetchResults">發(fā)送請求</button> {{value}} </div> </template> <script> import axios from '../axios.js' export default { data () { return { value: '初始值' } }, methods: { async fetchResults () { const response = await axios.get('mock/service') this.value = response.data console.log(this.value) } }, created (){ console.log(axios.get) } } </script>
// async.spec.js import { shallowMount } from '@vue/test-utils' import async from '../../../src/components/async' jest.mock('axios') it('當點擊按鈕發(fā)送請求時檢驗返回值', () => { const wrapper = shallowMount(async) console.log(jest) wrapper.find('button').trigger('click') // expect(wrapper.value) expect(wrapper.vm.value).toBe('response') // console.log(wrapper.vm.value).toBe('初始值') })
這個時候運行的話會報錯誤
因為斷言在 fetchResults 中的 Promise 完成之前就被調用了,所以value的值還是最開始的初始值。大多數(shù)單元測試庫都提供一個回調來使得運行期知道測試用例的完成時機。Jest 和 Mocha 都是用了 done。我們可以和 $nextTick 或 setTimeout 結合使用 done 來確保任何 Promise 都會在斷言之前完成。
- 測試 Vue Router 使用
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
Vue.js實現(xiàn)文件上傳壓縮優(yōu)化處理技巧
這篇文章主要介紹了Vue.js實現(xiàn)文件上傳壓縮優(yōu)化處理,本文給大家介紹兩種方法一種是借助canvas的封裝的文件壓縮上傳,二是使用compressorjs第三方插件實現(xiàn),本文給大家介紹的非常詳細需要的朋友可以參考下2022-11-11Vue中Element的table多選表格如何實現(xiàn)單選
這篇文章主要介紹了Vue中Element的table多選表格如何實現(xiàn)單選,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07vue基礎之使用get、post、jsonp實現(xiàn)交互功能示例
這篇文章主要介紹了vue基礎之使用get、post、jsonp實現(xiàn)交互功能,結合實例形式分析了vue.js中get、post及jsonp針對本地文件、網(wǎng)絡接口實現(xiàn)交互功能相關操作技巧,需要的朋友可以參考下2019-03-03解決前后端分離 vue+springboot 跨域 session+cookie失效問題
這篇文章主要介紹了前后端分離 vue+springboot 跨域 session+cookie失效問題的解決方法,解決過程也很簡單 ,需要的朋友可以參考下2019-05-05