Mocha是运行在nodejs和浏览器下的JavaScript的单元测试框架,官方文档在https://mochajs.org/,相当的容易上手和好用,单元测试框架其实都差不多,基本都包含下面内容:
用于写测试用例的宏,属性或者函数
断定库, 用于测试是否可以通过
辅助库,如hook库(测试前后调用某些函数或者方法),异常检查(某些函数在某些参数的情况下抛出异常), 输入组合(支持多排列的参数输入组合)等。
支持IDE的集成
下面就按照官方文档的顺序来简明扼要的
安装与初步的使用
在控制台窗口中执行下列命令:
$ npm install -g mocha $ mkdir test $ $EDITOR 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, [1,2,3].indexOf(5)); assert.equal(-1, [1,2,3].indexOf(0)); }); }); });
回到控制台:
$ mocha . ✔ 1 test complete (1ms)
这里mocha会查找当前文件目录下test文件夹下的内容,自动执行。
断定库
这个是判定测试用例是否通过,默认下可以用nodejs的assert库,与此同时,Mocha支持我们使用不同的断定库,现在可以支持下面的断定库,每个断定库的用法有一些差异,自己可以参考相应的文档。
1 should.js(https://github.com/shouldjs/should.js) BDD style shown throughout these docs (BDD模式,本文档用的都是这个断定库)
2 better-assert(https://github.com/tj/better-assert) c-style self-documenting assert()(C-模型下的断定库)
3 expect.js (https://github.com/Automattic/expect.js)expect() style assertions (expect模式的断定库)
4 unexpected() the extensible BDD assertion toolkit
5 chai(https://github.com/chaijs) expect(), assert() and should style assertions
同步代码
同步代码表示测试的是同步函数,上面的Array相关的例子代码就是。这个比较好理解。
异步代码
只所以有异步代码测试,原因是在nodejs上许多异步函数,如下面的代码中,只有done()函数执行完毕后,该测试用例才算完成
describe('User', function() { describe('#save()', function() { it('should save without error', function(done) { var user = new User('Luna'); user.saveAsync(function(err) { if (err) throw err; done(); // 只有执行完此函数后,该测试用例算是完成。 }); }); }); });
详解describe和it
上面的实例代码比较简单,那么什么是describe和it呢? 大致上,我们可以看出describe应该是声明了一个TestSuit(测试集合) ,而且测试集合可以嵌套管理,而it声明定义了一个具体的测试用例。 以bdd interface为例,具体的源代码如下:
/** * Describe a "suite" with the given `title` * and callback `fn` containing nested suites * and/or tests. */ context.describe = context.context = function(title, fn) { var suite = Suite.create(suites[0], title); suite.file = file; suites.unshift(suite); fn.call(suite); suites.shift(); return suite; }; /** * Describe a specification or test-case * with the given `title` and callback `fn` * acting as a thunk. */ context.it = context.specify = function(title, fn) { var suite = suites[0]; if (suite.pending) { fn = null; } var test = new Test(title, fn); test.file = file; suite.addTest(test); return test; };
Hooks(钩子)
实际上这个在写unit test是很常见的功能,就是在执行测试用例,测试用例集合前或者后需要某个回调函数(钩子)。Mocha提供了before(),after(), beforeEach() 和aftetEach(),示例代码如下:
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 });
hooks还有下列其他用法:
Describing Hooks - 可以对钩子函数添加描述,能更好的查看问题
Asynchronous Hooks (异步钩子): 钩子函数可以是同步,也可以是异步的,和测试用例一下,下面是异步钩子的示例代码:
beforeEach(function(done) { // 异步函数 db.clear(function(err) { if (err) return done(err); db.save([tobi, loki, jane], done); }); });
Root-Level Hooks (全局钩子) - 就是在describe外(测试用例集合外)执行,这个一般是在所有的测试用例前或者后执行。
Pending Tests (挂起测试)
就是有一些测试,现在还没有完成,有点类似TODO, 如下面的代码: