前端單元測試初探

原文發於個人博客:https://github.com/hwen/blogS...html

要不要寫單測?

關於這個 cnode 上就有個頗有意思的討論前端

作個調查,你的 Node 應用有寫單測嗎?node

看完這個應該會有結論?若是沒有,就回帖跟別人探討下~webpack

測試

測試有分爲git

  • 單元測試(單測)github

  • 集成測試web

  • 系統測試express

主要區別是單測傾向於測試模塊內部運行邏輯及功能,集成測試傾向於模塊間互相組合跟調用的測試。
系統測試(固然你要說,還有自動化測試)是對整個系統的測試,主要由測試人員而非開發人員負責。後端

本文只討論單測的範疇,對集成測試有興趣的話,能夠看下 Vue 的集成測試代碼。api

前端單測現狀

測試本質上就是假定一個輸入,而後判斷獲得預期的輸出。而前端與後端相比,夾雜着瀏覽器 DOM 操做,異步請求,
瀏覽器兼容性等方面的。要我來講,比後端寫單測要麻煩多了。。。

不過如今前端的單測已經發展得比較完善了,已經有一套比較完整的工具鏈,來完成各類需求。

單測工具鏈

框架

目前比較流行的測試框架有:

  • jasmine: 自帶斷言(assert),mock 功能

  • mocha:框架不帶斷言和mock功能,須要結合其餘工具。mocha 是 tj 大神寫的(tj 就是那個寫了express、koa、n、co、ejs的人。。。)

用得比較多的就上面兩個,還有一些用得比較少的,好比 Qunitintern

框架的實現原理其實就是檢測內部運行的代碼是否有拋出異常。而斷言庫若是沒有獲得預期的輸入時,就會拋出異常,給框架檢測到。

PS.想要學 mocha 和單測寫法,最好的資源就是 express 框架的測試代碼(狼叔推薦,親測很不錯)

斷言庫

  • chai:目前比較流行的斷言庫,支持 TDD(assert),BDD(expect、should)兩種風格

  • shouldjs:也是 tj 寫的,說實話我比較喜歡這個,可是有坑。。。後面會說到。。。

  • expectjs:基本是 shouldjs 的縮水版

  • assert:node 的核心模塊,node 環境能夠直接使用

mock 庫

  • sinon.js:只用過這個,其餘不大清楚。不過這個是目前最多人用的,基本夠了。支持 spies, stub, fake XMLHttpRequest, Fake server, Fake time,很強大

測試集成工具

  • karma:Google Angular 團隊寫的,功能很強大,有不少插件

  • buster.js: 這個支持 node 環境,但目前還在 beta 版(2017/11/4,版本0.7)。官網

半小時上手單測

(並非學會,就是這麼耿直 _(:з)∠)_,手是誰???)

使用的是:karma + mocha + chai + sinon(若是以前沒了解過這幾個,能夠邊寫邊看文檔,這樣學會快不少)

完整的例子能夠在這裏找到:GitHub 項目
建議把項目 clone 下來本身跑一遍,而後能夠本身加一些特效(啊,不對,是代碼纔對。。。

測試 DOM

詳細代碼,及配置見 源碼

it('test dom', () => {
  const div = document.getElementById('test')

  const content = div.innerHTML
  content.should.be.equal('here')

  setDivContent()
  const after = div.innerHTML
  after.should.be.equal('hallo world')
})

測試異步請求

it('test async', done => {
  getTopics()
    .then(res => {
      res.success.should.be.equal(true)
      done()
    })
    .catch(err => {
      info(err)
      done(err)
    })

})

調試技巧

調試技巧之一:善用 only

當你的單元測試越寫越多時,想測試新寫的單測是否正確時,能夠用 mocha 的 only
這樣作的好處有二:第一屏蔽其餘測試可使測試速度變得更快,第二屏蔽其餘測試,能夠在你新寫的測試錯誤時
肯定這個錯誤不是被其餘測試所影響致使的。

用法

describe.only('something', function() {
  // 只會跑包在裏面的測試
})

或者

it.only('do do', () => {
  // 只會跑這一個測試
})

調試技巧之二:善用 debug

要開啓 debug 的話,先在 karma.conf.jssingleRun 改爲 false
而後,看圖(懶得打字了 (:з)∠)

圖片描述

覆蓋率

生成覆蓋率報告也是至關簡單,不過有個要注意的地方就是
如今前端代碼不少都是通過 webpackbabel 編譯的,生成的代碼會多了不少二外的代碼

要解決這個問題使用babel-plugin-istanbul來替代karma-coverage就能夠了

preprocessors: {
      'src/**/*.js': ['webpack', 'coverage'],
      'test/*.test.js': ['webpack']
    }

將 karma-coverage 去掉,變成

preprocessors: {
      'src/**/*.js': ['webpack'],
      'test/*.test.js': ['webpack']
    }

而後在 webpack 配置添加 istanbul 插件

use: {
    loader: 'babel-loader',
    options: {
      plugins: ['istanbul']
    }
  }

最後能夠生成覆蓋率報告

cover1
cov2

另外有不少工具能夠對生成的覆蓋率報告進行進一步的分析,好比最多見的
你會在 Github 上常常見到的圖標

cov-icon

這個就是利用報告裏的lcovonly分析生成的

coverageReporter: {
  dir: 'test/coverage/',
  reporters: [
    { type: 'html', subdir: 'report-html' },
    { type: 'lcovonly', subdir: '.', file: 'report-lcovonly.txt' },  // 這裏,你能夠重命名 file
    { type: 'text-summary', subdir: '.', file: 'text-summary.txt' }
  ]
}

一些坑

  • 測試時若是有涉及瀏覽器事件(addEventListener),記得測試完移除掉,否則會對其餘的測試形成影響(afterEach -> removeEventListener)

  • mocha 裏使用箭頭函數須要注意,由於箭頭函數的 this 指向是靜態的,因此 this 並不指向 mocha(沒有 mocha 上下文)

  • 上面有說到,若是測試的是通過編譯的代碼,須要進行一些配置,目前的辦法是用babel-plugin-istanbul代替karma-cover來檢測覆蓋率

補充

前面有說到,爲何不用 should.js??由於若是你用 ES6 的語法寫單測(webpack 編譯),用 import should-sinon 會報錯。。(是否是由於 tj 大神寫完東西不喜歡維護的習慣致使should.js支持性很差???)

相關文章
相關標籤/搜索