如何为我的VUE项目编写高效的单元测试--Jest
Unit Testing(單元測試)--Jest
一個完整的測試程序通常由幾種不同的測試組合而成,比如end to end(E2E)測試,有時還包括整體測試、簡要測試和單元測試。這里要介紹的是Vue中的單元測試,使用流行的Jest JavaScript測試庫來運行我們的測試。
1.測試的目的
排除故障
每個應(yīng)用的開發(fā)中,多少會出現(xiàn)一些意料之外的bug。通過測試應(yīng)用程序,可以幫助我們大大減少此類問題,并增強應(yīng)用程序的邏輯性。
保證團隊成員的邏輯統(tǒng)一
如果您是團隊的新成員,并且對應(yīng)用程序還不熟悉,那么一組測試就好像是有經(jīng)驗的開發(fā)人員監(jiān)視你編寫代碼,確保您處于代碼應(yīng)該執(zhí)行的正確路線之內(nèi)。通過這些測試,您可以確信在添加新功能或更改現(xiàn)有代碼時不會破壞任何東西。
可以提高質(zhì)量代碼
當您在編寫vue組件時,由于考慮到測試,最好的方案將是創(chuàng)建獨立的、更可重用的組件。如果您開始為您的組件編寫測試,并且您注意到這些組件不容易測試,那么您可能會重構(gòu)您的組件,最終起到改進它們的效果。
起到很好的說明文檔作用
正如在第一點中提到的,測試的另一個結(jié)果是,它最終可以為您的開發(fā)團隊生成良好的文檔。當某人對代碼庫還不熟悉時,他們可以查看測試以獲得指導,這可以提供關(guān)于組件應(yīng)該如何工作的意圖的洞察,并為可能要測試的邊緣部分提供線索。
1.我們需要測試什么
在測試的過程中,很容易照成過分的測試一些不需要的東西,這會不必要地減慢開發(fā)時間。那么我們在Vue.js應(yīng)用程序中測試什么呢?答案其實很簡單:組件。由于Vue應(yīng)用程序是一個個組件相互組合而成的,我們需要測試它們各自的行為,以確保它們正常工作。
組件原理及分解
我們可以先分解組件,看看組件之間是怎么協(xié)調(diào)工作的。
一般來說,組件需要遵照我們定義的邏輯來工作,這里有一個輸入和輸出的概念。組件會接收一些靜態(tài)或動態(tài)的輸入值,然后依照邏輯輸出一些值或者是dom元素。
正常來說,組件的輸入輸出有以下這些:
1//輸入值
2
3//靜態(tài)接收數(shù)據(jù)
4ComponentData
5//動態(tài)接收數(shù)據(jù)
6ComponentProps
7//用戶互交,例如:一個用戶單擊的按鈕
8UserInteraction
9//生命周期邏輯,例如:mounted(),created()
10LifecycleMethods
11//組件狀態(tài)值
12VuexStore
13//路由參數(shù)
14RouteParams
15
16//輸出值
17
18//輸出的dom
19WhatisrenderedtotheDOM
20//外部調(diào)用的函數(shù)
21Externalfunctioncalls
22//組件觸發(fā)的事件
23Eventsemittedbythecomponent
24//路由的變更
25RouteChanges
26//組件狀態(tài)值得更新
27UpdatestotheVuexStore
28//對子組件的改變
29Connectionwithchildren
30
我們可以識別組件的輸入和輸出,挑選我們應(yīng)該測試的內(nèi)容,從而避開測試組件的內(nèi)部業(yè)務(wù)邏輯。換句話說,我們不應(yīng)該因為擔心每一行代碼如何工作而陷入困境。
這看起來可能有悖常理,但是單元測試的目標純粹是確保組件產(chǎn)生預(yù)期的結(jié)果。我們在這里不關(guān)心它是如何得出這個結(jié)果的。后期我們甚至可能會改變我們的邏輯方式,所以我們不希望測試如何實現(xiàn)這些邏輯。這些邏輯不是測試的工作。就單元測試而言,我們只要確保組件的輸出正常就行了。
要測試的部分
1<template>
2<div>
3<buttonv-show="loggedIn">Logout</button>
4</div>
5</template>
6
7<script>
8exportdefault{
9data(){
10return{
11loggedIn:false
12}
13}
14}
15</script>
在這個例子中,我們有一個組件,如果loggedIn屬性為true,它將顯示一個logout按鈕。為了弄清楚我們應(yīng)該測試這個組件的哪個部分,我們的第一步是確定組件的輸入和輸出。
1input
2
3//靜態(tài)數(shù)據(jù)
4data=>loggedIn
5//這個數(shù)據(jù)屬性決定按鈕是否顯示,所以這是一個我們應(yīng)該測試的輸入
6
7output
8
9Dom輸出(button)
10根據(jù)輸入(loggedIn),我們的按鈕應(yīng)該在什么時候顯示在DOM中
對于更復(fù)雜的組件,將有更多的方面需要測試,但同樣的方法也適用。
不測試的部分
對你應(yīng)該測試的東西知道大概當然是必要的,知道你不應(yīng)該測試的東西也是有幫助的。如下:
不測試組件邏輯的詳情(implementation details)
當單元測試時,我們不需要為某些邏輯是如何工作而煩惱,只要它們確實工作就行了。我們不在乎這里的內(nèi)部結(jié)構(gòu)。我們只關(guān)心組件產(chǎn)生了我們期望的輸出。
不要測試框架本身
開發(fā)人員經(jīng)常試圖測試太多,包括框架本身的內(nèi)部工作。但是框架作者已經(jīng)建立了這樣的測試。
例如,props中的數(shù)據(jù)類型,如果我們嘗試傳入錯誤數(shù)據(jù),Vue將拋出錯誤。我們不需要浪費時間測試Vue.js框架。這包括不要對Vue路由器和Vuex進行不必要的測試。
不測試第三方庫
如果您使用的第三方庫是高質(zhì)量的,那么它們已經(jīng)有了自己的測試。我們不需要測試它們的內(nèi)部結(jié)構(gòu)。例如,我們不需要測試Axios是如何工作的。Axios隊為我們做了這件事。
2.編寫單元測試
當我們使用Vue CLI創(chuàng)建應(yīng)用項目時:
首先需要選擇
Manually select features自定義一些項目配置
然后在選擇項目依賴時,勾選Unit Testing選項
最后在選擇測試方案時。選擇Jest
vue/cli項目可以這樣安裝
1vueadd@vue/unit-jest
2
3✔Successfullyinstalledplugin:@vue/cli-plugin-unit-jest
4//如果安裝的jest運行報錯可能是版本問題,可以嘗試npmupdate
這樣創(chuàng)建的項目中就為我們安裝好了依賴。
打開項目后,讓我們從查看package.json開始,在這里我們將看到為我們安裝了Jest和vue測試實用程序。
1//package.json
2"devDependencies":{
3"@vue/cli-plugin-unit-jest":"^3.11.0",
4"@vue/test-utils":"1.0.0-beta.29"
5}
Jest是一個JavaScript測試框架,它專注于簡化單元測試。Jest將為我們運行單元測試,并在測試通過或失敗時向我們報告。
API list:
1afterAll(fn,timeout)
2afterEach(fn,timeout)
3beforeAll(fn,timeout)
4beforeEach(fn,timeout)
5describe(name,fn)
6describe.each(table)(name,fn,timeout)
7describe.only(name,fn)
8describe.only.each(table)(name,fn)
9describe.skip(name,fn)
10describe.skip.each(table)(name,fn)
11test(name,fn,timeout)
12test.each(table)(name,fn,timeout)
13test.only(name,fn,timeout)
14test.only.each(table)(name,fn)
15test.skip(name,fn)
16test.skip.each(table)(name,fn)
17test.todo(name)
@vue/test-utils是Vue.js的官方單元測試實用程序庫。它使我們能夠在測試中渲染組件,然后對這些渲染的組件執(zhí)行各種操作。這使得我們可以測試組件的運行結(jié)果。
如何運行Jest測試,我們來查看
package.json中的運行腳本
1"scripts":{
2...
3"test:unit":"vue-cli-servicetest:unit"
4}
5//在我們編寫好測試代碼后只要運行:
6npmruntest:unit
7//或者在CLI中運行測試就可以運行測試代碼
8//這個命令的意思就是查看tests/unit目錄,并運行目錄下名為[componentsName].spec.js的文件。
查看項目根目錄下的tests/unit文件夾,有一個初始化的Example.spec.js文件。spec是specification的縮寫,即詳述組件運行規(guī)則的js文件
## demo1(測試一個方法)
創(chuàng)建函數(shù)文件demo1.js
1functionsum(a,b){
2returna+b;
3}
4module.exports=sum;
在tests/unit/中創(chuàng)建demo1.spec.js
1//導入要測試的文件
2constsum=require('./sum')
3
4//使用test(name,fn,timeout)創(chuàng)建一個測試
5test('adds1+2toequal3',()=>{
6expect(sum(1,2)).toBe(3)
7})
8
9//其中,name是對測試的描述,測試結(jié)果會打印
10//fn是要執(zhí)行的測試
11//expect()方法中描述的是測試的結(jié)果
12//toBe()是測試預(yù)期的值
運行這個單元測試
1npmruntest:unit
2
3PASStests/unit/demo1.spec.js
4?adds1+2toequal3(5ms)
5//PASS表示測試通過,函數(shù)運行正常
6//下面列出每一項text(),[test.name(測試使用的時間)]
## demo2(測試一個組件)
創(chuàng)建組件demo2.vue
1<template>
2<div>
3<buttonv-show="loggedIn">Logout</button>
4</div>
5</template>
6<script>
7exportdefault{
8data(){
9return{
10loggedIn:false
11}
12}
13}
14</script>
關(guān)于這個組件,前面我們已經(jīng)介紹過了,要測試的點如下:
如果用戶未登錄,則不顯示“注銷”按鈕
如果用戶已登錄,則顯示“注銷”按鈕
在tests/unit/中創(chuàng)建demo2.spec.js
1//導入要測試的組件
2importdemo2from'@/components/demo2'
3
4//因為我們要測試的是組件,所以我們在測試時需要加載這個組件
5//`@vue/test-utils`為我們提供了這項功能
6import{mount}from'@vue/test-utils'
7//使用describe(name,fn)創(chuàng)建一個測試組
8//當我們有多個測試時,用這種方式組織它們比較具有邏輯性
9
10describe('ComponentsDemo2',()=>{
11
12//其中寫所有組件內(nèi)需要的測試
13test('ifuserisnotloggedin,donotshowlogoutbutton',()=>{
14//安裝組件
15constwrapper=mount(AppHeader)
16
17//默認登錄狀態(tài)是false,則找到組件內(nèi)的btn,查看其可見性為false
18expect(wrapper.find('button').isVisible()).toBe(false)
19})
20test('ifauserisloggedin,showlogoutbutton',()=>{
21//安裝組件
22constwrapper=mount(AppHeader)
23
24//要測試登錄狀態(tài)是‘已登錄’,則先設(shè)置其狀態(tài)值
25wrapper.setData({loggedIn:true})
26
27//這時找到組件內(nèi)的btn,查看其可見性為true
28expect(wrapper.find('button').isVisible()).toBe(true)
29})
30})
提示:
您可能還會看到使用it()的測試塊,它是test()的別名。
@vue/test-utils,還提供shallowMount()方法。如果組件有子組件,shallowMount()將返回該組件的本身,而不是完全渲染的詳細組件單元測試的焦點是單一的組件,多數(shù)時候我們會忽略其子組件。
運行這個單元測試
1npmruntest:unit
2
3PASStests/unit/demo2.spec.js
4ComponentsDemo2
5?ifuserisnotloggedin,donotshowlogoutbutton(20ms)
6?ifauserisloggedin,showlogoutbutton(30ms)
7
8TestSuites:1passed,1total
9Tests:2passed,2total
10Snapshots:0total
11Time:2.653s
12Ranalltestsuites.
步驟總結(jié)如下圖:
創(chuàng)建一個測試組:describe()
開始一個測試:test()
安裝渲染組件:mount()
必要的時候設(shè)置組件參數(shù):setData()
調(diào)試預(yù)期的組件行為及數(shù)據(jù)正確與否:expect()
長按二維碼關(guān)注公眾號
總結(jié)
以上是生活随笔為你收集整理的如何为我的VUE项目编写高效的单元测试--Jest的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何解决使用JSON.stringify
- 下一篇: 鸿图之下孟优阵容怎么搭配