前言
本文屬於轉載內容,由於筆者是個小白,深知小白們在一些文章注釋不夠清楚時看不懂的痛苦,因此筆者在轉載的基礎上增加了每一行代碼的注釋,相信對你會有所幫助!
國外原文:https://scotch.io/amp/tutorials/how-to-write-a-unit-test-for-vuejs?from=timeline&isappinstalled=0
轉載自:https://www.cnblogs.com/chaoyuehedy/p/9163553.html
創建項目
創建 JavaScript 項目可能是一個復雜的過程。琳琅滿目的依賴庫供我們選擇。不過還好,我們可以使用vue-cli來創建VueJS項目,它幫我們包辦一切。運行 npm install 來安裝依賴:
npm install -g vue-cli
vue init webpack project-name
在這個過程中,你可能會遇到幾個提示。大多數提示比較簡單易懂,你可以直接選擇默認選項。需要注意的是,我們需要是否安裝 vue-router、Karma、Mocha的提示后輸入YES來引入這些工具。
如果你是新手,請按照下圖來進行創建文件:
下面簡單說明上圖的選項都是什么意思:
- name 文件名
- description 文件描述
- Author 作者
- Vue build 選擇第一個即可
- Install vue-router 輸入y(安裝vue路由)
- Use ESLint to lint your code? 輸入n(如果你只是想學一下單元測試的話,沒必要使用嚴格檢查)
- Set up unit tests 輸入y(建立單元測試)
- Pick a test runner 選擇第二個(Karma and Mocha)
- Setup e2e tests with Nightwatch? 輸入y
- 接下來選擇 Yue,use NPM
- 然后等待項目自動創建即可
接下來開始安裝依賴:
cd project-name // 進入項目的cmd
npm install
接下來我們執行下面的命令,這個命令將會在本地運行你的應用並在瀏覽器中打開。
npm run dev
如果你的網絡好的話,一會就裝好了。
依賴
Webpack (2.3) 是一個打包器,它可以合並打包JavaScript,CSS,HTML文件,並且提供給應用運行。Bable (v6.22) 是一個編譯器,用來把ES6編譯成ES5。目前有很多 JavaScript 標准在許多瀏覽器中還沒有被支持,所以需要將ES6轉成ES。
測試依賴
Karma (v1.4) 是一個運行時,它產生一個 Web 服務環境來運行項目代碼,並且執行測試。Mocha (v3.2) 是一個 JavaScript 測試框架。Chai (v3.5) 是一個 Mocha 可以使用的斷言庫。
在你的項目中,你可以找到下面這些目錄:build
、config
、node_modules
、src
、static
和 test
。對於本教程來說最重要的是src
,它包括我們應用的代碼,用來測試。
第一次測試
從最基本的開始去做一般都沒錯。我們將從創建簡單的列表組件開始。在 src/components
里創建一個新文件叫做 List.vue
並且將下面代碼寫進去。
<template>
<div>
<h1>My To Do List</h1>
</br>
<!--displays list -->
<ul>
<li v-for="item in listItems">{{ item }}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'list',
data () {
return {
listItems: ['buy food', 'play games', 'sleep'],
}
}
}
</script>
在這個組件中,列表項被儲存在數組(listItems
)里面。數據被傳遞到模板,然后被遍歷(v-for
),然后展現在頁面上。
當然,我們需要看到剛剛創建的列表,我們可以創建一個新的路由來展示這個組件。在src/router/index.js
中創建一個路由,添加完了代碼應該是下面這樣的:
import Vue from 'vue'
import Router from 'vue-router'
import Hello from '@/components/Hello'
import List from '@/components/List'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Hello',
component: Hello
},
{
path: '/to-do',
name: 'ToDo',
component: List
},
]
})
現在,訪問localhost:8080/#/to-do,可以看到我們做的應用。
接下來要寫測試的內容了,當然,如果你是一個新手,有很多API你可能看不太懂。在文章的最后有另一個代碼風格比較友好的版本,你可以自行選擇看哪一個版本。筆者是建議即便在你讀不懂的情況下,你也把代碼跟着敲一遍,因為筆者已經盡可能的把每一行代碼的注釋都寫的很清楚了。下面是寫代碼的步驟,當然,如果你想直接看全部代碼,可以往下翻,在全部代碼中,筆者也把注釋都寫的很清楚了。
首先,我們要測試的是數據的正確性。在test/unit/specs
目錄下創建一個List.spec.js
,並且寫入下面的代碼:
import List from '@/components/List';
import Vue from 'vue';
// 測試List.vue文件
describe('List.vue', () => {
// 'displays items from the list'是對本次測試的描述
it('displays items from the list', () => {
// our test goes here
})
})
在這個文件中,我們describe
了List.vue
組件,並且我們創建了一個空的測試,他將要檢查這個組件的列表展示。這是一個基本的 Mocha 測試文件。
我們首先要安裝我們的Vue組件。復制下面代碼放在測試文件的'our test goes here'
下面:
// build component
// 可以理解為獲取組件,如果你看不太懂的話,照抄就行了
const Constructor = Vue.extend(List);
const ListComponent = new Constructor().$mount();
我們繼承了Vue組件並且安裝這個組件。安裝組件很重要,只有這樣我們才能將通過模板來渲染HTML
。也就是說,HTML
已經被創建,並且我們模板中的變量(比如 item
)已經被填充內容,這樣我們就可以獲取HTML
了(使用$el
)。
我們的組件准備好了,我們可以寫第一個斷言。在這個例子中,我們使用Chai 斷言庫提供的 'expect' 模式,還有 'should' 和 'assert'模式。將下面的代碼放到,啟動組件的后面。
// assert that component text contains items from the list
// 下面是指本次測試期望組件中的文本內容包含:'play games'
expect(ListComponent.$el.textContent).to.contain('play games');
之前提到過,我們可以使用ListComponent.\$el
來獲取組件的HTML
,如果想去獲取HTML
內的內容(比如 文本),我們可以使用ListComponent.$el.textContent
。這個斷言用來檢查HTML
列表中的文本是否和組件的data
里的數據列表吻合。
下面是目前為止List.spec.js
中的所有代碼:
import List from '@/components/List';
import Vue from 'vue';
// 測試List.vue文件
describe('List.vue', () => {
// 'displays items from the list'是對本次測試的描述
it('displays items from the list', () => {
// 可以理解為獲取組件,如果你看不太懂的話,照抄就行了
const Constructor = Vue.extend(List);
const ListComponent = new Constructor().$mount();
// 下面是指本次測試期望組件中HTML的文本內容包含:'brush my teeth'
expect(ListComponent.$el.textContent).to.contain('play games');
})
為了檢查所有的事情都符合我們的預期,我們可以運行測試!通過 vue-cli
創建的項目,我們可以簡單的使用npm run unit
來運行cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run
。
npm run unit
如果測試都通過了,將會有一個綠色的列表來顯示測試報告,讓你了解測試都覆蓋了哪些代碼。
模擬用戶輸入(進階,其實也很簡單)
雖然前面的功能贊贊噠,但沒有多少應用只是用來展示數據。下一步我們要做到是添加新的項目到to-do list
中。看這里,我們創建了一個input
框來輸入內容,然后創建一個button
用來提交內容。下面是更新后的 List.vue
:
<template>
<div>
<h1>My To Do List</h1>
</br>
<input v-model="newItem" >
<button @click="addItemToList">Add</button>
<!-- displays list -->
<ul>
<li v-for="item in listItems">{{ item }}</li>
</ul>
</div>
</template>
<script>
export default {
name: 'test',
data () {
return {
listItems: ['buy food', 'play games', 'sleep'],
newItem: ''
}
},
methods: {
addItemToList() {
this.listItems.push(this.newItem);
this.newItem = '';
}
}
}
</script>
使用v-model
,輸入框里面的內容將和newItem
進行雙向綁定。當按鈕被點擊后,執行addItemToList
,將newItem
添加到to-do list
數組里面,並且清空newItem
里面的內容,新的項目將會被添加到列表中。
可以為新功能寫測試文件了,創建List.spec.js
,並且添加以下測試代碼。
it('adds a new item to list on click', () => {
// our test goes here
})
第一步,我們需要創建我們的組件,並且模擬一個用戶在輸入框的輸入行為。因為 VueJs 將輸入框和 newItem
變量進行了綁定,我們可以給newItem
設置內容。
// build component
const Constructor = Vue.extend(List);
const ListComponent = new Constructor().$mount();
// set value of new item
ListComponent.newItem = 'brush my teeth';
下一步,我們需要點擊按鈕。我們需要在HTML
中找到按鈕,在$el
中即可找到。這是,我們可以使用querySelector
,像選擇真實元素一樣選擇這個按鈕。也可以使用class(.buttonClass)
、ID(#buttonID)
或者標簽名(button)
來選擇。
// find button
const button = ListComponent.$el.querySelector('button');
為了模擬點擊,我們需要給按鈕一個新的事件對象。在測試環境中,List
組件不會監聽任何事件,因此我們需要手動運行watcher
。
// simulate click event
const clickEvent = new window.Event('click');
button.dispatchEvent(clickEvent);
ListComponent._watcher.run();
最后,我們需要檢查我們添加的新項目是否顯示在HTML
中,這個在前面已經介紹過。我們也需要檢查newItem
是否被存儲在了數組里面。
// assert list contains new item
expect(ListComponent.$el.textContent).to.contain('brush my teeth');
expect(ListComponent.listItems).to.contain('brush my teeth');
下面是整個測試文件的內容:
import List from '@/components/List';
import Vue from 'vue';
// 測試List.vue文件
describe('List.vue', () => {
// 'displays items from the list'是對第一次測試的描述
it('displays items from the list', () => {
// 下面兩行可以理解為獲取組件,如果你看不太懂的話,照抄就行了
const Constructor = Vue.extend(List);
const ListComponent = new Constructor().$mount();
// 下面是指本次測試期望組件中的文本內容包含:'play games'
expect(ListComponent.$el.textContent).to.contain('play games');
})
// 'adds a new item to list on click'是對第二次測試的描述
it('adds a new item to list on click', () => {
// build component
// 下面兩行可以理解為獲取組件,如果你看不太懂的話,照抄就行了
const Constructor = Vue.extend(List);
const ListComponent = new Constructor().$mount();
// set input value
// 初始化輸入的內容
ListComponent.newItem = 'brush my teeth';
// simulate click event
// 獲取點擊按鈕
const button = ListComponent.$el.querySelector('button');
// 新建點擊事件
const clickEvent = new window.Event('click');
// 按鈕執行點擊事件
button.dispatchEvent(clickEvent);
// 由於v-model雙向綁定,數據會發生變化,因此使用watch監聽
ListComponent._watcher.run();
// assert list contains new item
// 下面是指本次測試期望組件中的節點的文本內容包含:'brush my teeth'
expect(ListComponent.$el.textContent).to.contain('brush my teeth');
// 下面是指本次測試期望組件中的data中包含:'brush my teeth'
expect(ListComponent.listItems).to.contain('brush my teeth');
})
})
現在跑一次這個測試,應該全是綠色的。
希望你讀這些代碼的時候思路能夠清晰,不過它對於剛剛開始接觸VueJs單元測試的人來說可讀性並不是很高。有一個VueJS實用程序庫,它將一些復雜的代碼進行了封裝。如果想使用它,可以在項目的根目錄下輸入以下命令安裝。(這就是前面提到的另一個版本)
npm install avoriaz
下面這個測試實際上和上面測試相同,只不過寫法上有些不同。我們使用了mount()
法來安裝Vue組件,使用find()
獲取按鈕,使用dispatch()
來觸發點擊。由於只是寫法上有所不同,因此這個測試代碼就不寫注釋了,這個測試的代碼風格還是非常友好的。
import { mount } from 'avoriaz';
import List from '@/components/List';
import Vue from 'vue';
describe('List.vue', () => {
// previous tests ..
it('adds new item to list on click with avoriaz', () => {
// build component
const ListComponent = mount(List);
// set input value
ListComponent.setData({
newItem: 'brush my teeth',
});
// simulate click event
const button = ListComponent.find('button')[0];
button.dispatch('click');
// assert list contains new item
expect(ListComponent.text()).to.contain('brush my teeth');
expect(ListComponent.data().listItems).to.contain('brush my teeth');
})
})
總結
在日常工作以及JavaScript開發中,尤其是VueJS項目,測試是非常重要的。因為剛開始接觸測試的時候,我遇到了一些問題,所以總結出一篇文章供大家參考。希望這篇文章能夠幫到所有像我一樣的人。