小編給大家分享一下怎么為vue的項(xiàng)目添加單元測(cè)試,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
成都創(chuàng)新互聯(lián)成立于2013年,先為南湖等服務(wù)建站,南湖等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為南湖企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。
動(dòng)機(jī)
單元測(cè)試能避免出現(xiàn)一些代碼運(yùn)行結(jié)果與預(yù)期不符的錯(cuò)誤,通常是一些比較低級(jí)但又難以發(fā)現(xiàn)的問(wèn)題。
粗心且懶,在每次調(diào)整之后,需要不斷地檢查代碼,反復(fù)去走流程。擔(dān)心由于自己的改動(dòng)而導(dǎo)致了邏輯上的錯(cuò)誤。而這里面的一大部分工作其實(shí)可以讓單元測(cè)試來(lái)完成。
有了單元測(cè)試之后,可以對(duì)代碼本身形成一種規(guī)范。如果在進(jìn)行單元測(cè)試過(guò)程中發(fā)現(xiàn)自己的一些代碼不方便進(jìn)行測(cè)試,那么你可能需要重新審視這些代碼,看是否有一些設(shè)計(jì)上不合理或者可以優(yōu)化的地方。
嵌入了單元測(cè)試的項(xiàng)目顯得更加的專業(yè),也會(huì)更有逼格,測(cè)試本身是開(kāi)發(fā)環(huán)節(jié)需要做的內(nèi)容。
工具選取對(duì)比(一個(gè)合適測(cè)試框架 -- Jest)
之前也沒(méi)有去接觸過(guò)前端的單元測(cè)試,也是這幾天開(kāi)始了解,開(kāi)始并沒(méi)有頭緒,所以就在網(wǎng)上以及github上去看了一些之前比較流行的測(cè)試框架。發(fā)現(xiàn)比較流行的是karma + mocha + Chrome的組合。當(dāng)我單獨(dú)一個(gè)個(gè)去看的時(shí)候,發(fā)現(xiàn)其內(nèi)容還是比較的多的。之后選取了jest也是經(jīng)過(guò)對(duì)比權(quán)衡的
優(yōu)點(diǎn)
1、一站式的解決方案,學(xué)習(xí)成本更低,上手更快(很適合現(xiàn)如今我的需求)
在使用 Jest 之前,我需要一個(gè)測(cè)試框架(mocha),需要一個(gè)測(cè)試運(yùn)行器(karma),需要一個(gè)斷言庫(kù)(chai),需要一個(gè)用來(lái)做 spies/stubs/mocks 的工具(sinon 以及 sinon-chai 插件),一個(gè)用于測(cè)試的瀏覽器環(huán)境(可以是 Chrome 瀏覽器,也可以用 PhantomJS)。 而使用 Jest 后,只要安裝它,全都搞定了。
2、全面的官方文檔,易于學(xué)習(xí)和使用
Jest 的官方文檔很完善,對(duì)著文檔很快就能上手。而在之前,我需要學(xué)習(xí)好幾個(gè)插件的用法,至少得知道 mocha 用處和原理吧 我得學(xué)會(huì) karma 的配置和命令,chai 的各種斷言方法……,經(jīng)常得周旋于不同的文檔站之間,其實(shí)是件很煩也很低效的事
3、更直觀明確的測(cè)試信息提示
4、方便的命令行工具
缺點(diǎn)
jsdom 的一些局限性:因?yàn)?Jest 是基于 jsdom 的,jsdom 畢竟不是真實(shí)的瀏覽器環(huán)境,它在測(cè)試過(guò)程中其實(shí)并不真正的“渲染”組件。這會(huì)導(dǎo)致一些問(wèn)題,例如,如果組件代碼中有一些根據(jù)實(shí)際渲染后的屬性值進(jìn)行計(jì)算(比如元素的 clientWidth)就可能出問(wèn)題,因?yàn)?jsdom 中這些參數(shù)通常默認(rèn)是 0.
綜上所述,最終我確定下來(lái)的方案是使用成熟好用的測(cè)試工具庫(kù) --- vue-test-utils 其前身是 avoriaz,avoriaz 也是一個(gè)不錯(cuò)的包,但其 README 中有說(shuō)明,當(dāng) vue-test-utils 正式發(fā)布的時(shí)候, 它將會(huì)被廢棄。 vue-test-utils 能極大地簡(jiǎn)化 Vue.js 單元測(cè)試。 例如:Vue 單元測(cè)試,一般是像下面這樣的(包括 vue-cli 提供的模板里默認(rèn)也是這樣):
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 h2').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 h2').text()).to.equal('Welcome to Your Vue.js App') }) })
可以看到代碼更加簡(jiǎn)潔了。wrapper 內(nèi)含許多有用的方法,上面的例子中所使用的 find() 其中最簡(jiǎn)單不過(guò)的一個(gè)。vue-test-utils 還有 createLocalVue() 等方法以及 stub 之類的功能,基本上可以完成絕大部分情況下的測(cè)試用例,這也是非常的實(shí)用的了。
安裝使用
安裝使用的方式很簡(jiǎn)單,由于想引入到現(xiàn)有的項(xiàng)目中來(lái),現(xiàn)有的項(xiàng)目大多是vue-cli創(chuàng)建的,所以一開(kāi)始的時(shí)候基本上是已經(jīng)安裝并配置好了 webpack、vue-loader 和 Babel。如果是比較原始的項(xiàng)目,也是可以單獨(dú)安裝的。
我們要做的第一件事就是安裝 Jest 和 Vue Test Utils:
$ npm install --save-dev jest @vue/test-utils
然后我們需要在 package.json 中定義一個(gè)單元測(cè)試的腳本。
// package.json { "scripts": { "test": "jest" } }
在 Jest 中處理單文件組件
npm install --save-dev vue-jest
接下來(lái)在 package.json 中創(chuàng)建一個(gè) jest 塊:
{ // ... "jest": { "moduleFileExtensions": [ "js", "json", // 告訴 Jest 處理 `*.vue` 文件 "vue" ], "transform": { // 用 `vue-jest` 處理 `*.vue` 文件 ".*\\.(vue)$": "vue-jest" } } }
具體的使用步驟
此處我根據(jù)自己的需求來(lái)進(jìn)行整理
對(duì)頁(yè)面內(nèi)容的測(cè)試
// viewTest.vue{{ msg }}
1212121
// event.spec.js // 從測(cè)試實(shí)用工具集中導(dǎo)入 `mount()` 方法 // 同時(shí)導(dǎo)入你要測(cè)試的組件 import { mount } from '@vue/test-utils' import Component from '../../../src/components/itemEvent' describe('事件觸發(fā)測(cè)試', () => { test('事件觸發(fā)測(cè)試', () => { // 現(xiàn)在掛載組件,你便得到了這個(gè)包裹器 const wrapper = mount(Component) const button = wrapper.find('button') wrapper.setData({ newItem: '添加測(cè)試項(xiàng)', }) button.trigger('click') console.log(wrapper.text()) expect(wrapper.text()).toContain('添加測(cè)試項(xiàng)') }) })
這里是在模擬用戶交互的一個(gè)測(cè)試,當(dāng)用戶點(diǎn)擊按鈕的時(shí)候會(huì)把數(shù)據(jù)插入到當(dāng)前的列表中來(lái),所以最開(kāi)始需要定位到這個(gè)按鈕,可以用find(),之后要去觸發(fā)這個(gè)事件, button.trigger('click'),然后把預(yù)期的結(jié)果,與按照流程的結(jié)果相比較,以達(dá)到測(cè)試的效果。這里模擬的是一個(gè)點(diǎn)擊事件,當(dāng)然,api也支持各種的鼠標(biāo)事件以及鍵盤(pán)事件。
測(cè)試異步行為 平時(shí)的業(yè)務(wù)場(chǎng)景中肯定是離不開(kāi)異步操作的,當(dāng)發(fā)送一個(gè)接口請(qǐng)求的時(shí)候應(yīng)該怎么去才做。Jest 運(yùn)行測(cè)試用例同時(shí)可以模擬了 HTTP 庫(kù) axios,對(duì)預(yù)期結(jié)果可以進(jìn)行設(shè)定和比較,比如:
// axios.js export default { get: () => Promise.resolve({ data: 'response' }) }
{{value}}
// async.spec.js import { shallowMount } from '@vue/test-utils' import async from '../../../src/components/async' jest.mock('axios') it('當(dāng)點(diǎn)擊按鈕發(fā)送請(qǐng)求時(shí)檢驗(yàn)返回值', () => { 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('初始值') })
這個(gè)時(shí)候運(yùn)行的話會(huì)報(bào)錯(cuò)誤
因?yàn)閿嘌栽?fetchResults 中的 Promise 完成之前就被調(diào)用了,所以value的值還是最開(kāi)始的初始值。大多數(shù)單元測(cè)試庫(kù)都提供一個(gè)回調(diào)來(lái)使得運(yùn)行期知道測(cè)試用例的完成時(shí)機(jī)。Jest 和 Mocha 都是用了 done。我們可以和 $nextTick 或 setTimeout 結(jié)合使用 done 來(lái)確保任何 Promise 都會(huì)在斷言之前完成。
以上是“怎么為vue的項(xiàng)目添加單元測(cè)試”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!