摩卡:以编程方式创build并完成testing

我想要代理testing结果在其他环境上实时运行。

下面是一些我想实现的伪代码:

var test = proxy.getCurrentTest(); // => {slow: 200, timeout: 2000, duration: 235, result: 'error'}; var tmpIt = it('test1', function(){ this.slow(test.slow); this.timeout(test.timeout); }); tmpIt.close({ duration: test.duration, result: test.result }); // this should make this test red in the output, // because the `result` is not 'success' 

无论如何设置testing的结果和持续时间没有“真正”运行吗? 并获得所有的视觉摩卡输出到terminal?

编辑:这个问题不是关于如何将testing结果forms的subprocess传递给主进程。 它已经在为我工作。

希望我正确理解这些要求。 我所实施的是将摩卡咖啡整合到摩卡咖啡中的testing结果。

为了与mocha集成,这个实现描述了一个自定义的mocha接口来代理在另一个环境中执行的testing的testing结果。

为了使用这个接口,在运行摩卡时必须将-uparameter passing给摩卡

 > mocha -u ./path/to/proxy-interface ... 

请注意./path/to/proxy-interface是mocha在require调用中要求接口模块的path。

代理接口负责向mocha的BDD接口这样的全局上下文提供一个proxyTest函数,调用传递的函数获取testing结果并转发testing结果,同时保留testing运行器显示的执行testing的数量。

 var Mocha = require('mocha'); var Suite = Mocha.Suite; var Test = Mocha.Test; var escapeRe = require('escape-string-regexp'); module.exports = function(suite) { var suites = [suite]; suite.on('pre-require', function(context, file, mocha) { // A bit hacky since we require mocha internal common interface module var common = require('mocha/lib/interfaces/common')(suites, context); context.run = mocha.options.delay && common.runWithSuite(suite); context.proxyTest = function(title, fn) { var suite = suites[0]; if (suite.pending) { fn = null; } var test = new ProxyTest(title, fn); test.file = file; suite.addTest(test); return test; }; }); }; var Runnable = Mocha.Runnable; var inherits = require('util').inherits; function ProxyTest(title, fn) { Runnable.call(this, title, null); this.pending = !fn; this.type = 'test'; this.body = (fn || '').toString(); this.fn = fn; } inherits(ProxyTest, Runnable); ProxyTest.prototype.run = function(done) { var proxiedTestResult = this.fn(); this.duration = proxiedTestResult.duration; this.timedOut = this.timeout() > proxiedTestResult.timeout; done(proxiedTestResult.result); }; ProxyTest.prototype.clone = function() { var test = new ProxyTest(this.title, this.fn); test.timeout(this.timeout()); test.slow(this.slow()); test.enableTimeouts(this.enableTimeouts()); test.retries(this.retries()); test.currentRetry(this.currentRetry()); test.globals(this.globals()); test.parent = this.parent; test.file = this.file; test.ctx = this.ctx; return test; }; 

上面的代码覆盖了Mocha的Runnable运行实现,并运行传递的函数来获取testing结果,并将ProxyTest接口中的必需字段设置为与mochatesting兼容。

用法

在你的testing中,使用proxyTest global来注册一个新的mochatesting

 var proxy = { getErrorTestResult() { return {slow: 200, timeout: 2000, duration: 50, result: 'error'}; }, getTimeoutTestResult() { return {slow: 200, timeout: 2000, duration: 3000 }; }, getSlowTestResult() { return {slow: 200, timeout: 2000, duration: 235 }; }, getSuccessTestResult() { return {slow: 200, timeout: 2000, duration: 50 }; } } proxyTest('error', proxy.getErrorTestResult); proxyTest('timeout', proxy.getTimeoutTestResult); proxyTest('slow', proxy.getSlowTestResult); proxyTest('success', proxy.getSuccessTestResult); 

产量

摩卡输出

启示

这种方法的缺点是一个自定义接口必须传递给摩卡并且你不能使用摩卡BDD词汇表像describe 。 第二个缺点可以消除,如果你“扩展”(在这种情况下:复制一些代码)摩卡的BDD接口:

 var Mocha = require('mocha'); /** * Module dependencies. */ var Suite = Mocha.Suite; var Test = Mocha.Test; var escapeRe = require('escape-string-regexp'); /** * BDD-style interface - extended with proxy functionality: * * describe('Array', function() { * describe('#indexOf()', function() { * it('should return -1 when not present', function() { * // ... * }); * * it('should return the index when present', function() { * // ... * }); * }); * }); * * @param {Suite} suite Root suite. */ module.exports = function(suite) { var suites = [suite]; suite.on('pre-require', function(context, file, mocha) { // A bit hacky since we require mocha internal common interface module var common = require('mocha/lib/interfaces/common')(suites, context); context.before = common.before; context.after = common.after; context.beforeEach = common.beforeEach; context.afterEach = common.afterEach; context.run = mocha.options.delay && common.runWithSuite(suite); /** * 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; }; /** * Pending describe. */ context.xdescribe = context.xcontext = context.describe.skip = function(title, fn) { var suite = Suite.create(suites[0], title); suite.pending = true; suites.unshift(suite); fn.call(suite); suites.shift(); }; /** * Exclusive suite. */ context.describe.only = function(title, fn) { var suite = context.describe(title, fn); mocha.grep(suite.fullTitle()); return suite; }; /** * Describe a specification or test-case * with the given `title` and callback `fn` * acting as a thunk. */ var it = 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; }; /** * Exclusive test-case. */ context.it.only = function(title, fn) { var test = it(title, fn); var reString = '^' + escapeRe(test.fullTitle()) + '$'; mocha.grep(new RegExp(reString)); return test; }; /** * Pending test case. */ context.xit = context.xspecify = context.it.skip = function(title) { context.it(title); }; /** * Number of attempts to retry. */ context.it.retries = function(n) { context.retries(n); }; context.proxyTest = function(title, fn) { var suite = suites[0]; if (suite.pending) { fn = null; } var test = new ProxyTest(title, fn); test.file = file; suite.addTest(test); return test; }; }); }; var Runnable = Mocha.Runnable; var inherits = require('util').inherits; function ProxyTest(title, fn) { Runnable.call(this, title, null); this.pending = !fn; this.type = 'test'; this.body = (fn || '').toString(); this.fn = fn; } inherits(ProxyTest, Runnable); ProxyTest.prototype.run = function(done) { var proxiedTestResult = this.fn(); this.duration = proxiedTestResult.duration; this.timedOut = this.timeout() > proxiedTestResult.timeout; done(proxiedTestResult.result); }; ProxyTest.prototype.clone = function() { var test = new ProxyTest(this.title, this.fn); test.timeout(this.timeout()); test.slow(this.slow()); test.enableTimeouts(this.enableTimeouts()); test.retries(this.retries()); test.currentRetry(this.currentRetry()); test.globals(this.globals()); test.parent = this.parent; test.file = this.file; test.ctx = this.ctx; return test; };