前端單測的那些事

前言

由於常常須要維護一些大型的業務項目和一些本身的開源項目,因此爲了更好的「規範」代碼質量和迭代的穩定性,開始寫了一些單測。下面也主要是本身的一些總結吧,因爲測試工具和框架不少,這裏只介紹一些browser端經常使用的測試工具,文中若是有問題也歡迎拍正!!🙂javascript

爲什麼要測試

以前咱們開發項目的時候,老是會忽略去寫一寫單測,大多數緣由多是以爲沒有時間或者是浪費時間。並且還須要去維護測試用例。 其實通常項目隨着時間的遷移,會變得愈來愈複雜和龐大,這時候若是咱們對某一個公共模塊改動,而其餘人也依賴了這個模塊,可能就會致使別人的功能出現bug。 有了自動化測試,開發者會更加信任本身的代碼。開發者不再會害怕將代碼交給別人維護,不用擔憂別的開發者在代碼裏搞「破壞」。後人接手一段有測試用例的代碼,修改起來也會更加從容。測試用例裏很是清楚的闡釋了開發者和使用者對於這端代碼的指望和要求,也很是有利於代碼的傳承。html

一些概念

TDD (Test Driven Development)

TDD 也就是測試驅動開發,簡單的說,即在寫任何功能代碼以前,先寫它的測試代碼。具體步驟:前端

  • 根據須要編寫一個測試用例
  • 編寫功能代碼,以讓剛纔的測試用例經過
  • 逐步補充測試用例
  • 修改功能代碼使新增的測試用例和原來的都經過
  • 重構,包括功能代碼和測試用例

BDD(Behaviour Driven Development)

BDD 即 行爲驅動開發,能夠理解爲也是 TDD 的分支,即也是測試驅動,但 BDD 強調的是寫測試的風格,即測試要寫得像天然語言,運用一些好比expect、should等跟天然語言相近的斷言,讓項目的各個成員甚至產品都能看懂測試,甚至編寫測試。java

寫法對比

不論是 TDD 仍是 BDD,咱們來對比一些兩者的寫法:node

// TDD
  suite('Array', function() {
    setup(function() {
    });

    test('equal -1 when index beyond array length', function() {
      assert.equal(-1, [1,2,3].indexOf(4));
    });
  });

  // BDD
  describe('Array', function() {
    before(function() {
    });

    it('should return -1 when no such index', function() {
      [1,2,3].indexOf(4).should.equal(-1);
    });
  });
複製代碼

簡單的看, BDD 風格寫的會更容易理解,更加語義化。webpack

斷言(assert)

在單元測試時,開發預計在程序運行到某個節點位置,須要判斷某些邏輯條件必須知足,這樣下面的一些業務邏輯才能夠進行下去,若是不知足,程序就會"報錯"甚至是"崩潰"。斷言在單測中,也是主要用來肯定某段程序執行結果應該是某個值這樣的一個預期。git

一些斷言庫的比較

斷言庫即提供一套 API 幫助開發者在單元測試的過程當中斷定某個值是否符合預期,好比:es6

should.js
value.should.equal(1);
  value.should.be.an.Object();
複製代碼
expect.js
expect(value).to.be(1)
expect(value).to.be.an('object')
複製代碼

chai

Chai is a BDD / TDD assertion library for node and the browser that can be delightfully paired with any javascript testing framework.github

chai 提供了三種斷言風格來分別適用於 BDD 和 TDD。expect/should API 對應BDD風格,Assert API 對應TDD風格。 web

image

測試框架

所謂"測試框架",就是運行測試的工具。經過它,能夠爲JavaScript應用添加測試,從而保證代碼的質量。

Mocha

Mocha(發音"摩卡")誕生於2011年,是如今最流行的JavaScript測試框架之一,在瀏覽器和Node環境均可以使用。 更多關於mocha的使用和介紹能夠參考阮老師的這篇文章測試框架 Mocha 實例教程

Jasmine

Jasmine 不依賴於任何框架,因此適用於全部的 Javascript 代碼。使用一個全局函數 describe 來描述每一個測試,而且能夠嵌套。describe函數有2個參數,一個是字符串用於描述,一個是函數用於測試。在該函數中可使用全局函數it 來定義Specs,也就是單元測試的主要內容, 使用 expect 函數來測試:

describe("A suite is just a function", function() {
  var a;
  it("and so is a spec", function() {
    a = true;
    expect(a).toBe(true);
  });
});
複製代碼

前端測試工具

相比於服務端開發,前端開發在測試方面始終面臨着一個嚴峻的問題,那就是瀏覽器兼容性。前端開發中瀏覽器兼容性是一個永遠的問題,並且我認爲即便解決了瀏覽器的兼容性問題,將來在移動開發方面,設備兼容性也是一個問題。

因此在自動化測試方面也是如此,即便全部的單元測試集中在了一個runner中,前端測試仍然要面對至少4個瀏覽器內核以及3個電腦操做系統加2個或更多移動操做系統,況且還有令移動開發人員頭疼的Android的碎片化問題。不過能夠安心的是,早已存在這樣的工具能夠捕獲不一樣設備上的不一樣瀏覽器,並使之隨時更新測試結果,甚至能夠在一個終端上看到全部結果。下面咱們主要介紹 Karma

Karma

Karma是一個基於 Node.js 的 JavaScript 測試執行過程管理工具(Test Runner)。該工具可用於測試全部主流Web瀏覽器,也可集成到 CI(Continuous integration)工具,也可和其餘代碼編輯器一塊兒使用。這個測試工具的一個強大特性就是,它能夠監控(Watch)文件的變化,而後自行執行,經過console.log顯示測試結果。

文檔

Istanbul

測試的時候,咱們經常關心,是否全部代碼都測試到了。 這個指標就叫作"代碼覆蓋率"(code coverage)。它有四個測量維度。

  • 行覆蓋率(line coverage):是否每一行都執行了?
  • 函數覆蓋率(function coverage):是否每一個函數都調用了?
  • 分支覆蓋率(branch coverage):是否每一個if代碼塊都執行了?
  • 語句覆蓋率(statement coverage):是否每一個語句都執行了?

這個軟件以土耳其最大城市伊斯坦布爾命名,由於土耳其地毯世界聞名,而地毯是用來覆蓋的。

詳細的文檔參考阮老師的代碼覆蓋率工具 Istanbul 入門教程

動手!

下面咱們來搭建一個ES6 + jasmine + karma + Istanbul + webpack 的基礎測試工具。 首先來搭建一個簡單的es6環境:

mkdir example

cd example

npm i babel-core bable-loader babel-preset-env --save
複製代碼

而後建立.babelrc文件

{
    "presets": [
        "env"
    ]
}
複製代碼

接着咱們須要安裝 karma 測試工具:

$ npm install karma --save-dev

$ npm install karma-jasmine karma-chrome-launcher jasmine-core --save-dev
複製代碼

接下來初始化karma:

karma init
複製代碼

image

這樣目錄中便會多了一個karma.conf.js這樣的一個文件。爲了在測試的時候可使用es6,咱們須要使用karma-webpack

npm i webpack karma-webpack --save
複製代碼

接下來,就是咱們熟悉的工做了,寫一個加載測試腳本的webpack配置文件,好比webpack.test.js:

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  }
};
複製代碼

再改寫一下咱們的karma.conf.js, 引入webpack:

const webpack = require('../webpack.config')

module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine'],
    files: [
      'test/**/*.spec.js'
    ],
    exclude: [
    ],
    preprocessors: {
      'test/add.spec.js': ['webpack']
    },
    webpack: webpack,
    reporters: ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false,
    concurrency: Infinity
  })
}
複製代碼

運行karma start

image

當前咱們的reporters設置的是progress,因此只會展現最終測試結果,和執行錯誤的語句。若是你想看到每一條的執行結果,能夠安裝karma-spec-reporter

npm install karma-spec-reporter --save-dev
複製代碼

而後加入spec到karma.conf.js 的 reporters中:

reporters: ['spec']
複製代碼

這樣就會生成這樣的形式報告:

image

其次咱們須要添加istanbul進行代碼覆蓋率測試。首先咱們須要安裝一個babel插件:

npm install babel-plugin-istanbul --save-dev 
複製代碼

而後修改咱們的.babelrc文件:

{
  // ...
  "env": {
    "test": {
      "presets": ["env"],
      "plugins": ["istanbul"]
    }
  }
}
複製代碼

經過使用.babelrc裏的env屬性,當咱們經過設置BABEL_ENV=test的時候即可以去執行代碼測試的相關插件,這在複雜項目中的測試配置中頗有用。 接下來,爲了能生成覆蓋率測試報告,咱們還須要安裝一個 karma Istanbul 插件karma-coverage:

npm install karma karma-coverage --save-dev
複製代碼

而後咱們改一下package.json裏面的script腳本:

"scripts": {
    "test": "cross-env BABEL_ENV=test karma start test/karma.conf.js"
}
複製代碼

運行

npm run test
複製代碼

打開 coverage裏面的index.html文件:

image

能夠看到覆蓋率的一些測試結果。可是這樣有點不太方便,但願能能夠直接在控制檯輸出就行了。因此咱們須要改一下karma.conf.js文件,加上這樣一個屬性:

coverageReporter: {
    dir: './coverage',
    reporters: [
        { type: 'lcov', subdir: '.' },
        { type: 'text-summary' } // 在控制檯輸出摘要
    ]
}
複製代碼

這樣咱們在控制檯即可以打印出基本的覆蓋率測試結果:

image

至此。已經完成了一個測試環境的搭建,能夠知足大部分工程的單測配置。

結語

可能平時因爲你們更加關心業務代碼,而會忽略一些前端的測試工做,網上的資料也是零零碎碎的,沒有一個系統的總結和介紹。這裏整理了一些測試工具的使用方法,但願能夠對你有所幫助。而後本文全部代碼和原始出處發表在我的博客中。也歡迎閱讀以前的博文:

muwoo 的 blogs

單測demo

參考文章

測試框架 Mocha 實例教程

代碼覆蓋率工具 Istanbul 入門教程

Node.js 單元測試:我要寫測試

關於前端開發談談單元測試

相關文章
相關標籤/搜索