本文全面介紹如何使用Mocha,讓你輕鬆上手。如果你以前對測試一無所知,本文也可以當作JavaScript單元測試入門。用於寫入測試案例的宏,屬性或函數
斷定庫, 用於測試是否可以透過輔助庫,如hook庫(測試前後調用某些函數或方法),異常檢查(某些函數在某些參數的情況下
拋出異常), 輸入組合(支援多排列的參數輸入組合)等。的
安裝與初步的使用在控制台視窗中執行下列命令:
$ npm install -g mocha $ mk dir 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 BDD style shown throughout these docs (BDD模式,本文檔用的都是這個斷定庫)
2 better-assert) c-style self-documenting assert()(C-模型
下的斷定庫)3 expect.js expect() style assertions (expect模式的斷定庫)
4 unexpected the extensible BDD assertion toolkit5 chai 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 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; };
回呼函數
(鉤子)。 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, 如下面的程式碼:describe('Array', function() {
describe('#indexOf()', function() {
// pending test below 暂时不写回调函数
it('should return -1 when the value is not present');
});
});
Exclusive Tests (排它測試)排它測試就是允許一個測試集合或測試案例,只有一個被執行,其他都被跳過。如下面測試案例集合:
describe('Array', function() { describe.only('#indexOf()', function() { // ... }); // 测试集合不会被执行 describe('#ingored()', function() { // ... }); });
以下是對於測試案例:
describe('Array', function() { describe('#indexOf()', function() { it.only('should return -1 unless present', function() { // ... }); // 测试用例不会执行 it('should return the index when present', function() { // ... }); }); });
需要說明的是,對於Hooks(回呼函數)會被執行。
Inclusive Tests(包含測試)
與only函數相反,skip函數,將會讓mocha系統無視當前的測試用例集合或測試用例,所有被skip的測試用例將被報告為Pending。
下面是對與測試案例集合的範例程式碼:
describe('Array', function() { //该测试用例会被ingore掉 describe.skip('#indexOf()', function() { // ... }); // 该测试会被执行 describe('#indexOf()', function() { // ... }); });
下面範例是針對特定的測試案例:
describe('Array', function() { describe('#indexOf()', function() { // 测试用例会被ingore掉 it.skip('should return -1 unless present', function() { // ... }); // 测试用例会被执行 it('should return the index when present', function() { // ... }); }); });
Dynamically Generating Tests(動態產生測試案例)
其實這個在很多其他的測試工具,如NUnit也會有,就是將測試案例的參數用一個集合代替,從而產生不同的測試用例。以下是具體的例子:
var assert = require('assert'); function add() { return Array.prototype.slice.call(arguments).reduce(function(prev, curr) { return prev + curr; }, 0); } describe('add()', function() { var tests = [ {args: [1, 2], expected: 3}, {args: [1, 2, 3], expected: 6}, {args: [1, 2, 3, 4], expected: 10} ]; // 下面就会生成三个不同的测试用例,相当于写了三个it函数的测试用例。 tests.forEach(function(test) { it('correctly adds ' + test.args.length + ' args', function() { var res = add.apply(null, test.args); assert.equal(res, test.expected); }); }); });
Interfaces(
介面)
#Mocha的介面系統允許使用者用不同風格的函數或樣式寫他們的測試案例集合和具體的測試案例,mocha有BDD,TDD,Exports,QUnit和Require 風格的介面。
BDD - 這個是mocha的預設樣式,我們在本文中的範例程式碼就是這樣的格式。
其提供了describe(), context(), it(), before(), after(), beforeEach(), and afterEach()的函數,範例程式碼如下:
#
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); }); }); }); });
TDD - 提供了 suite(), test(), suiteSetup(), suiteTeardown(), setup(), 和 teardown()的函数,其实和BDD风格的接口类似(suite相当于describe,test相当于it),示例代码如下:
suite('Array', function() { setup(function() { // ... }); suite('#indexOf()', function() { test('should return -1 when not present', function() { assert.equal(-1, [1,2,3].indexOf(4)); }); }); });
Exports - 对象的值都是测试用例集合,函数值都是测试用例。 关键字before, after, beforeEach, and afterEach 需要特别定义。
具体的示例代码如下:
module.exports = { before: function() { // ... }, 'Array': { '#indexOf()': { 'should return -1 when not present': function() { [1,2,3].indexOf(4).should.equal(-1); } } } };
QUnit - 有点像TDD,用suit和test函数,也包含before(), after(), beforeEach()和afterEach(),但是用法稍微有点不一样, 可以参考下面的代码:
function ok(expr, msg) { if (!expr) throw new Error(msg); } suite('Array'); test('#length', function() { var arr = [1,2,3]; ok(arr.length == 3); }); test('#indexOf()', function() { var arr = [1,2,3]; ok(arr.indexOf(1) == 0); ok(arr.indexOf(2) == 1); ok(arr.indexOf(3) == 2); }); suite('String'); test('#length', function() { ok('foo'.length == 3); });
Require - 该接口允许我们利用require关键字去重新封装定义 describe ,it等关键字,这样可以避免全局变量。
如下列代码:
var testCase = require('mocha').describe; var pre = require('mocha').before; var assertions = require('mocha').it; var assert = require('assert'); testCase('Array', function() { pre(function() { // ... }); testCase('#indexOf()', function() { assertions('should return -1 when not present', function() { assert.equal([1,2,3].indexOf(4), -1); }); }); }); 上述默认的接口是BDD, 如果想
上述默认的接口是BDD, 如果想使用其他的接口,可以使用下面的命令行:
mocha -ui 接口(TDD|Exports|QUnit...)
Reporters (测试报告/结果样式)
Mocha 支持不同格式的测试结果暂时,其支持 Spec, Dot Matrix,Nyan,TAP…等等,默认的样式为Spec,如果需要其他的样式,可以用下列命令行实现:
mocha --reporter 具体的样式(Dot Matrix|TAP|Nyan...)
Editor Plugins
mocha 能很好的集成到TextMate,Wallaby.js,JetBrains(IntelliJ IDEA, WebStorm) 中,这里就用WebStorm作为例子。 JetBrains提供了NodeJS的plugin让我们很好的使用mocha和nodeJs。 添加mocha 的相关的菜单,
这里就可以直接在WebStorm中运行,调试mocha的测试用例了。
以上是詳細介紹NodeJs測試框架Mocha的安裝與使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!