单元测试之:mocha和chai

@youngwind 2015-12-19 05:21:46发表于 youngwind/blog 其他

前言

本文说4件事。

  1. 简单例子
  2. 简单例子升级版
  3. 测试reducers
  4. 参考资料

简单例子

mocha是众多自动化测试框架之一,chai也是众多断言库之一。

安装

npm install mocha -g
npm install chai -g

编写test.js

// test.js 演示对字符串的split方法的测试
var assert = require('chai').assert;
describe("string#split", function () {
  it("should return an array", function () {
    assert(Array.isArray('a,b,c'.split(',')));
  });
  it('should return the same array', function () {
    assert.equal(['a', 'b', 'c'].length, 'a,b,c'.split(',').length, 'arrays have equal lenght');
    for (var i = 0; i < ['a', 'b', 'c'].length; i++) {
      assert.equal(['a', 'b', 'c'][i], 'a,b,c'.split(',')[i], i + 'element is equal');
    }
  })
});

执行test.js

mocha test

执行结果

2015-11-29-mocha-test


简单例子升级版

上面的代码是不是很多的冗余?假如有很多个describe或者it,该如何组织划分呢?

编写test-pro.js

// test-pro.js
var expected, current;

// 在每个describe之前执行
before(function () {
  expected = ['a', 'b', 'c'];
});
describe('String#split', function () {
  // 在每一个it之前执行
  beforeEach(function () {
    current = 'a,b,c'.split(',');
  });

  it('should return an array', function () {
    assert(Array.isArray(current))
  });


  it('should return the same array', function () {
    assert.equal(expected.length, current.length, 'array have equal length');
    for (var i = 0; i < expected.length; i++) {
      assert.equal(expected[i], current[i], i + 'element is equal');
    }
  });

});

执行结果

2015-11-29-mocha-test2


测试reducers

拆分reducers

原先我的多个reducer是写在一个js文件当中,然后再通过combinereducers结合起来。
后来在写测试用例的时候发现这样不好,所以把每个reducer拆成一个js文件。
然后在rootreducer结合起来,这样就可以针对不同的reducer写单元测试了。

reducer样例add.js

// 假设我有一个add.js的reducer
var ActionTypes = require('../constants/ActionTypes');

function search(state, action) {
  if (!state) {
    state = 0;
  }
  switch (action.type) {
    case ActionTypes.ADD_TAG:
      return state + 1;

    default:
      return state
  }
}

module.exports = search;

编写相应的测试文件search-test.js

// 测试文件search-test.js
var assert = require('chai').assert;

var search = require('../src/reducers/add');

describe("test-search#search", function () {
  it("should return + 1", function () {
    var state = 1;
    var nextState = 2;
    assert.equal(nextState, search(state, {type: "ADD_TAG"}));
  });

  it("should return self", function () {
    var state = 1;
    var nextState = 1;
    assert.equal(nextState, search(state, {type: "Others"}));
  });
});

以此类推,每个reducer写一个测试文件,然后统一放在test目录下面,比如我的目录结构是这样的。
2015-11-29-mocha-test3
2015-11-29-mocha-test4

执行测试

mocha --compilers js:babel-core/register  --recursive
// mocha有很多配置参数,这里的compilers表示测试前用babel对其进行编译,因为我的reducer用了ES6语法。
// --recursive表示级联测试,会搜索并执行本目录下所有的测试

执行结果

2015-11-29-mocha-test5

小技巧:假如不想每次测试都输入这么多东西,可以将这行命令写入package.json的script当中,比如像这样。
2015-11-29-mocha-test6

那么以后只要执行npm test,就相当于执行相对应的命令了。

参考资料

1. [http://mochajs.org/](http://mochajs.org/) 2. [https://github.com/chaijs/chai](https://github.com/chaijs/chai) 3. [http://www.kuqin.com/shuoit/20131204/336779.html](http://www.kuqin.com/shuoit/20131204/336779.html) 4. [http://www.shaynegui.com/javascript-unit-test-chaijs/](http://www.shaynegui.com/javascript-unit-test-chaijs/)