前端單元測試 實現教程 mocha + mochawesome + istanbul + sinon + chai

爲何要寫單元測試css

  • 減小bug
  • 提升代碼質量,保證你的代碼是可測試的
  • 放心重構

當你每一個方法都寫了單元測試的時候,你每個改動都會影響相應的單元測試,這樣你不用費盡心思的考慮哪裏會有影響,特別是複雜項目或非核心功能(不易被測試到),從而致使bug的產生。html

當你的代碼不可測試的時候,就得考慮你的代碼是否須要重構的。好的代碼應該是職責分明且單一,顆粒度小且易於測試。前端

當你重構時,特別是大範圍的重構,你就有勇氣和信心了。node


那麼單元測試須要有那些要素呢jquery

  • 測試框架
  • 測試報表
  • 測試覆蓋率
  • 斷言
  • mock

測試框架選用 mocha 官方文檔git

安裝es6

npm install mocha

package.jsongithub

"scripts": {
        "test": "mocha --recursive --require babel-core/register tests/Js/test"
    }

mocha默認會找到項目的根目錄下的 test目錄,可是不少人項目目錄中單元測試目錄並非test,而是在/tests/Js/test中,在scripts中,後面加上單元測試路徑,就能夠修改默認地址npm

recursive參數表明查找 目錄的全部子目錄下的單元測試,不然只會查找當前目錄下的單元測試json

node中並不支持某些es6語法,須要經過babel編譯,因此須要添加 --require babel-core/register

同時須要在項目根目錄添加.babelrc文件

{
  "presets": [ "es2015" ]
}

如今在 tests/Js/test目錄下建立一個文件 test.js

var assert = require('assert');
describe('Array', function() {
  describe('#indexOf()', function() {
    it('should return -1 when the value is not present', function() {
      assert.equal([1,2,3].indexOf(4), -1);
    });
  });
});

命令行中執行 npm run test 結果以下
圖片描述

以上咱們知道了如何引入前端測試框架,es6語法問題,執行路徑問題


有時候命令行的結果看着不明瞭,想要輸出測試報告呢
這時候可使用 mochawesome
安裝

npm install --save-dev mochawesome

package.json

"scripts": {
        "test": "mocha --recursive --reporter mochawesome --require babel-core/register tests/Js/test"
    }

在scripts命令中,添加 --reporter mochawesome
執行命令

npm run test

結果如圖,將會生成 html文件和json文件
圖片描述
圖片描述


"代碼覆蓋率"(code coverage)。它有四個測量維度。

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

那麼如何知道每一個js的覆蓋率呢
這時候用到了 istanbul 和 babel-istanbul
安裝

npm install istanbul
npm install babel-istanbul

package.json

"scripts": {
     "test:cover": "babel-node ./node_modules/.bin/babel-istanbul cover _mocha -- tests/Js/* -R spec --recursive
    }

istanbul他也是不支持一些es6語法的,因此也須要babel轉譯
使用cover參數結合mocha,--表明後面參數傳遞給mocha

執行命令

npm run test:cover

結果如圖
圖片描述

圖片描述

Mocha自己不帶斷言庫,因此必須先引入斷言庫。
咱們這裏使用 chai

npm install chai

chaijs有三種斷言風格,詳細查看官網


jquery做爲大部分都在使用的庫,那麼如何對這類的代碼進行單元測試呢
好比如下代碼
hide-element.js

export const hideElement = ($element) => {
  $element.on('click', '.hide', function() {
    $(this).hide();
  });
};

首先node環境和瀏覽器環境是不同的,因此咱們跑這類的單元測試就須要模擬出瀏覽器環境
咱們須要安裝 jsdom

npm install jsdom

test.js 以下

const assert = require('chai').assert;
const { hideElement } = require('xxxx/hide-element.js');
describe('test:hide-element.js', function(done) {
  before(function() {
    let { JSDOM } = require('jsdom');
    let dom = new JSDOM(`<!DOCTYPE html><html><body><div class="hide"></div></body></html>`,{
    url: 'http://127.0.0.1/',
    referrer: 'http://127.0.0.1/',
    contentType: 'text/html',
    userAgent: 'Mellblomenator/9000',
    includeNodeLocations: true,
  });
    global.window = dom.window;
    global.$ = require('jquery');
    
    hideElement($('body'));
  });
  it('click event', function() {
    $('body').find('.hide').trigger('click');
    assert.equal($('.hide').css('display'), 'none');
  });
});
  1. mocha 由 describe,it基本元素組成
  2. mocha 有四個鉤子函數 before,after,beforeEach,afterEach
  3. 由於node中引入依賴時會緩存模塊,初始化jsdom環境時,最好在before中,防止污染jsdom環境,致使不一樣的單元測試之間互相影響

須要測試的代碼中依賴了其餘的模塊時,爲了測試須要測試的代碼,而不去關心依賴的模塊,這時候咱們須要 sinon 去mock掉相關依賴

demo.js

import api from 'api';
export const demo = (arg) => {
    if (arg == 1) {
      return api.get({
        params: params
      });
    }
    
    return 'ok';
};

test.js

import { demo } from 'xx/demo.js';
const assert = require('chai').assert;
const sinon = require('sinon');
import api from 'api';

describe('demo', function() {
  it('demo(1)', function() {
    //mock api的get方法,而且指定返回值爲 'N'
    let apiGet = sinon.stub(api, 'get').returns('N');
    let expectedParams = {params: 'yes'};
    let res = demo(1);
    //automate clean-up,防止影響其餘單元測試
    apiGet.restore();
    //斷言調用api.get 是傳入的參數爲 {params: 'yes'}
    sinon.assert.calledWith(apiGet, expectedParams);
    
    assert.equal(res, 'N');
  });
});
相關文章
相關標籤/搜索