[譯] 如何爲 Vue 項目寫單元測試

譯者:明非html

連接:https://fanmingfei.com/posts/A_Vue_Unit_Text_Tutorial.html前端

原文:https://scotch.io/amp/tutorials/how-to-write-a-unit-test-for-vuejs?from=timeline&isappinstalled=0vue

衆所周知,Vue.js 是一個很是牛逼的 JavaScript 框架,對於建立複雜功能的前端項目是很是有用的。不論是什麼項目,檢查應用是否正常工做,運行是否爲預期,是尤其重要的。然而,爲了保證業務正常運行,咱們的項目,每作一次更新,都要對全部功能作一次迴歸測試,隨着項目的增大,重複的測試工做愈來愈多,愈來愈乏味,手工測試將變成一個噁心的事情。正因如此,自動化測試誕生了,它能夠隨時監測咱們的代碼是否正常工做,運行結果是否符合預期。在這個教程中,咱們將建立一個簡單的VueJS項目,併爲其寫一個簡單的單元測試。node

咱們建立一個基本的 to-do list 組件進行測試。咱們將要測試的是,列表展現是否正確,用戶是否能夠正常添加到 to-do list。經過這個教程,你將學會如何去爲你的組件寫一個測試,測試包括HTML展現是否正確以及用戶的操做是否能正常進行。webpack

這個git庫是這篇文章的全部代碼。git

建立項目

建立 JavaScript 項目多是一個複雜的過程。琳琅滿目的依賴庫供咱們選擇。不過還好,咱們可使用vue-cli來建立VueJS項目,它幫咱們包辦一切。運行 npm install 來安裝依賴:github

npm install -g vue-cli
vue init webpack project-nameweb

在這個過程當中,你可能會遇到幾個提示。大多數提示比較簡單易懂,你能夠直接選擇默認選項。須要注意的是,咱們須要是否安裝 vue-routerKarmaMocha的提示後輸入YES來引入這些工具。而後開始安裝依賴:vue-router

cd project-name
npm installvue-cli

接下來咱們執行下面的命令,這個命令將會在本地運行你的應用並在瀏覽器中打開。

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 可使用的斷言庫。

在你的項目中,你能夠找到下面這些目錄:buildconfignode_modulessrcstatictest。對於本教程來講最重要的是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,能夠看到咱們作的應用。

首先,咱們要測試的是數據的正確性。在test/unit/specs目錄下建立一個List.spec.js,而且寫入下面的代碼:

import List from '@/components/List';
import Vue from 'vue';

describe('List.vue', () => {

  it('displays items from the list', () => {
      // our test goes here
  })
})

在這個文件中,咱們_describing_了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
expect(ListComponent.$el.textContent).to.contain('play games');

以前提到過,咱們可使用ListComponent.$el來獲取組件的HTML,若是想去獲取HTML內的內容(好比 文本),咱們可使用ListComponent.$el.textContent。這個斷言用來檢查HTML列表中的文本是否和組件的data裏的數據列表吻合。

爲了檢查全部的事情都符合咱們的預期,咱們能夠運行測試!經過 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';

describe('List.vue', () => {
  it('displays items from the list', () => {
    const Constructor = Vue.extend(List);
    const ListComponent = new Constructor().$mount();
    expect(ListComponent.$el.textContent).to.contain('play games');
  })

  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);
    ListComponent._watcher.run();

    // assert list contains new item
    expect(ListComponent.$el.textContent).to.contain('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項目,測試是很是重要的。由於剛開始接觸測試的時候,我遇到了一些問題,因此總結出一篇文章供你們參考。但願這篇文章可以幫到全部像我同樣的人。

這個git庫是此次教程全部的代碼。

相關文章
相關標籤/搜索