Mocha是JavaScript/Nodejs的一個非常優秀的測試架構,本身就支援同步和非同步測試,不過,非同步測試由於要顯式調用done(),容易造成非同步代碼callback嵌套過深,不利於看懂和維護測試代碼:
it('async test', function(done) { doSomethingA(function (err, r1) { // check... doSomethingB(function (err, r2) { // check... done(); }); });});
於是這位老兄想到用ES6的generator來測試:Yield to the test: using Mocha with ES6 generators。
如果用generator編寫測試代碼,就可以寫成:
it('async test', function*() { var r1 = yield doSomethingA(); // check... var r2 = yield doSomethingB(); // check...});
這麼寫當然比較爽了,可惜Mocha的開發人員還不打算引入co來支援generator,所以,測試代碼還得改成:
it('async test', function() { return co(function*() { var r1 = yield doSomethingA(); // check... var r2 = yield doSomethingB(); // check... });});
每個TestCase都要多寫幾行完全一樣的代碼,自然不爽。於是這位老兄改寫了mocha.Runnable.prototype.run:
mocha.Runnable.prototype.run = function(fn) { ...}
不得不說,這位老兄想法挺好,但是改錯了地方,最新版的Mocha 2.1.0代碼和他改的版本已經有很大不同了,要改也應該改Runnable的建構函式,這樣改動最小,也最簡單。
先把co的源碼下載一份,命名為co.js,然後修改:
// 新加:var co = require('./co');function isGeneratorFunction(obj) { var constructor = obj.constructor; return constructor && 'GeneratorFunction' == constructor.name;} // ENDfunction Runnable(title, fn) { // 新加: if (isGeneratorFunction(fn)) { var f = fn; fn = function () { return co(f); }; } // END ...}
isGeneratorFunction是從co的源碼複製出來的。改完了,就可以直接運行generator的TestCase了。