前端单元测试 完成教程 mocha + mochawesome + istanbul + sinon + chai

为何要写单元测试

  • 削减bug
  • 进步代码质量,保证你的代码是可测试的
  • 宁神重构

当你每一个要领都写了单元测试的时刻,你每一个修正都邑影响响应的单元测试,如许你不必费尽心思的斟酌那里会有影响,特别是庞杂项目或非核心功能(不容易被测试到),从而致使bug的发生。

当你的代码不可测试的时刻,就得斟酌你的代码是不是须要重构的。好的代码应该是职责清楚且单一,颗粒度小且易于测试。

当你重构时,特别是大范围的重构,你就有勇气和自信心了。

那末单元测试须要有那些要素呢

  • 测试框架
  • 测试报表
  • 测试覆蓋率
  • 断言
  • mock

测试框架选用 mocha 官方文档

装置

npm install mocha

package.json

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

mocha默许会找到项目的根目次下的 test目次,然则很多人项目目次中单元测试目次并非test,而是在/tests/Js/test中,在scripts中,背面加上单元测试途径,就能够修正默许地点

recursive参数代表查找 目次的一切子目次下的单元测试,不然只会查找当前目次下的单元测试

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 效果以下
《前端单元测试 完成教程 mocha + mochawesome + istanbul + sinon + chai》

以上我们晓得了怎样引入前端测试框架,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文件
《前端单元测试 完成教程 mocha + mochawesome + istanbul + sinon + chai》
《前端单元测试 完成教程 mocha + mochawesome + istanbul + sinon + chai》

“代码覆蓋率”(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 + mochawesome + istanbul + sinon + chai》

《前端单元测试 完成教程 mocha + mochawesome + istanbul + sinon + chai》

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');
  });
});
    原文作者:jay_tian
    原文地址: https://segmentfault.com/a/1190000013900214
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞