Mocha

JavaScript單元測試工具介紹 

Mocha 特色

  •  JavaScript單元測試工具 
  • 可在Node.js與瀏覽器上執行, 實作前後端的測試腳本
  • 支援兩種測試模式
    • BDD (Behavior Driven Development 
    • TDD (Test Driven Development)
  • 搭配多種的斷言庫(Assertions)

BDD與TDD 比較

BDD TDD
全名 Behavior Driven Development
行為驅動開發
Test Driven Development
測試驅動開發
主要特色 單元測試的一種
測試流程導向
注重專案整體運作的邏輯
以簡單和自然化方式檢視
單元測試的一種
測試功能導向
注重功能結果是否正常
 

BDD

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

    describe('#indexOf()', function() {
      context('when not present', function() {
        it('should not throw an error', function() {
          (function() {
            [1,2,3].indexOf(4);
          }).should.not.throw();
        });
        it('should return -1', function() {
          [1,2,3].indexOf(4).should.equal(-1);
        });
      });
      context('when present', function() {
        it('should return the index where the element first appears in the array', function() {
          [1,2,3].indexOf(3).should.equal(2);
        });
      });
    });
  });

常用方法: describe(),  context(), it(), before(), after(), beforeEach(), afterEach()

TDD

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

  suite('#indexOf()', function() {
    test('should return -1 when not present', function() { 
      assert.equal(-1, [1,2,3].indexOf(4));
    });
  });
});

常用方法:

suite(), test(), suiteSetup(), suiteTeardown(), setup(), teardown()

安裝步驟

簡單‧快速

安裝 

$ npm install -g mocha --save-dev

-  安裝 mocha

$ npm install chai   //nodejs 

http://chaijs.com/chai.js // browser

 - 安裝 chai.js

建立mocha專案

 - 快速建立測試專案 

$ mocha init [專案位置路徑]
root -|
      |- index.html
      |- mocha.css
      |- mocha.js
      |- test.js
      |- node_modules
      |- package.json

幾個簡單的範例

  • Nodejs環境測試
    • 基礎範例
    • 非同步測試
    • 進階用法
    • 測試結果種類
  • 瀏覽器環境測試

 

Node.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, [1,2,3].indexOf(5));
      assert.equal(-1, [1,2,3].indexOf(0));
    });
  });
});

test.js: 

執行測試

$ mocha test.js

測試結果 成功案例

測試結果- 發現錯誤

非同步執行範例

function User(name){
	var person = {}
	person.save = function (cb){
		if(name){
			console.log("開始save")
			console.log("save中...")
			setTimeout(function(){
				console.log("花費一秒...")
				cb(false)
			}, 1000)
		}
		else
			cb("no name!")
	}
	person.name = name
	return person
}

describe('User', function() {
  describe('#save()', function() {
    it('should save without error', function(done) {
      var user = new User('Luna');
      console.log("執行save")
      user.save(function(err) {
        if (err) throw err;
        done();
      	console.log("save完成")
      });
    });
  });
});

要done, 才做下一個

執行結果

測試結果- 發現錯誤

callback fucntion 有誤, 導致執行時間過長而中止, 預設是兩秒

測試結果- 發現錯誤

this.timeout: 自訂timeout時間長度

describe('User', function() {
    this.timeout(15000); //設定timeout時間最大值

    it('should save without error', function(done) {
        // ...
    )}
});

進階用法

Hooks

describe('hooks', function() {

  before(function() {
    // runs before all tests in this block
  });

  after(function() {
    // runs after all tests in this block
  });

  beforeEach(function() {
    // runs before each test in this block
  });

  afterEach(function() {
    // runs after each test in this block
  });

  // test cases
});

範例

describe('Connection', function() {
  var db = new Connection, 
    tobi = new User('tobi'), 
    loki = new User('loki'), 
    jane = new User('jane');

  beforeEach(function(done) {
    db.clear(function(err) {
      if (err) return done(err);
      db.save([tobi, loki, jane], done);
    });
  });

  describe('#find()', function() {
    it('respond with matching records', function(done) {
      db.find({type: 'User'}, function(err, res) {
        if (err) return done(err);
        res.should.have.length(3);
        done();
      });
    });
  });
});

輸出型態

- mocha reporters

mocha [file] -R dot

mocha [file] -R list

mocha [file] -R JSON

參考文獻

附錄

其他工具比較

Mocha 與其他工具比較

Qunit Jasmine Mocha
發展時間 2008~ 2010~ 2012~
最新版本 V 1.20.0 V 2.4.1 V 2.3.4
執行環境 broswer broswer JavaScript
Node.js
browsers 
特色 由JQuery團隊開發, 但獨立於JQuery, 主要運行在瀏覽器作單元測試 將BBD測試風格引入Javascript測試
優點 - 輕量, 只需一個js與css即可
 - 不須依靠其他套件或框架
 
-可支援Ant, Maven等自動建構工具整合
- 輕量, 只需一個js與css即可
- 用法貼近自然語言
無內建斷言庫
支援各種斷詞(assertion)庫
缺點 自動化測試支援差, 很難與Ant, Maven等自動建構工具整合 本身不支援Node.js, 須由第三方套件支持
 
 需要經常配合其他套件如: chai等使用,配置麻烦,維護成本高

QUnit 

QUnit.test( "hello test", function ( assert ) {
  assert.ok( 1 == "1", "Passed!" );
});

QUnit.test('成功結果', function (assert) {
	assert.ok(window.fibonacci(0) == "0", "好的!")
});

QUnit.test('錯誤結果', function (assert) {
	assert.ok(window.fibonacci(0) == "1", "壞的!")
});

測試結果

Jasmine 

describe('測試一', function () {
  it('should equal 0 when n === 0', function () {
  	expect(window.fibonacci(0)).toEqual(0)
  });
});

describe('測試二', function () {
  it('should equal 1 when n === 1', function () {
  	expect(window.fibonacci(1)).toEqual(1)
  });
});
  

測試結果

偵測錯誤

Mocha

var should = chai.should();
// var assert = require('assert');


describe('測試一', function () {
  it('should equal 0 when n === 0', function () {
    window.fibonacci(0).should.equal(0);
    // assert.equal(0, window.fibonacci(0))
  });
});

describe('測試二', function () {
  it('should equal 0 when n === 0', function () {
    window.fibonacci(0).should.equal(1);
    // assert.equal(0, window.fibonacci(0))
  });
});
  

測試結果

Made with Slides.com