Subscribed unsubscribe Subscribe Subscribe

qunit-tapを使ってnode.jsのテストをproveで行う 続編

Perl Node.js

qunit-tapを使ってnode.jsのテストをproveで行う - すぎゃーんメモ の続きです。
qunit-tapは1.0.0がreleaseされました。
https://github.com/twada/qunit-tap/commit/5da16418b6de71e4be186d080a0622e5689e8878


で、@さんから追加情報をいただきました。

とのこと。

exports = module.exports = global;

var path = require('path');
QUnit = require(path.join(path.dirname(require.resolve('qunit-tap')), '..', 'vendor', 'qunit', 'qunit', 'qunit')).QUnit;
require("qunit-tap").qunitTap(QUnit, require("sys").puts, { noPlan: true });

QUnit.init();
exports.assert = QUnit;

とhelper scriptを用意している場合、

require('../test_helper.js');

QUnit.test('hoge', function() {
    assert.ok(true);
});

QUnit.start();

のような単純なテストは問題ないですが

require('../test_helper.js');

QUnit.test('hoge', function() {
    for (var i = 0; i < 30000; i++) {
        assert.ok(true);
    }
});

QUnit.start();

のように、時間のかかるテストを行うと、上手くいきません。

$ prove --ext=.js --exec=node
t/hoge.js .. 29145/?
node.js:134
        throw e; // process.nextTick error, or 'error' event on first tick
        ^
TypeError: Object #<Object> has no method 'setTimeout'
    at process (/Users/sugyan/.nvm/v0.4.4/lib/node/.npm/qunit-tap/1.0.0/package/vendor/qunit/qunit/qunit.js:861:11)
    at Object.start (/Users/sugyan/.nvm/v0.4.4/lib/node/.npm/qunit-tap/1.0.0/package/vendor/qunit/qunit/qunit.js:412:4)
    at Object.<anonymous> (/Users/sugyan/temp/qunit-tap/t/hoge.js:9:7)
    at Module._compile (module.js:404:26)
    at Object..js (module.js:410:10)
    at Module.load (module.js:336:31)
    at Function._load (module.js:297:12)
    at Array.<anonymous> (module.js:423:10)
    at EventEmitter._tickCallback (node.js:126:26)
t/hoge.js .. Dubious, test returned 1 (wstat 256, 0x100)
All 30000 subtests passed

Test Summary Report
-------------------
t/hoge.js (Wstat: 256 Tests: 30000 Failed: 0)
  Non-zero exit status: 1
  Parse errors: No plan found in TAP output
Files=1, Tests=30000,  3 wallclock secs ( 2.27 usr  0.01 sys +  0.29 cusr  0.06 csys =  2.63 CPU)
Result: FAIL

で、helper scriptで"QUnit.config.updateRate"を0にすると上手くいくようになります。

exports = module.exports = global;

var path = require('path');
QUnit = require(path.join(path.dirname(require.resolve('qunit-tap')), '..', 'vendor', 'qunit', 'qunit', 'qunit')).QUnit;
require("qunit-tap").qunitTap(QUnit, require("sys").puts, { noPlan: true });

QUnit.init();
QUnit.config.updateRate = 0;
exports.assert = QUnit;

どうやらqunit.jsの中でこの設定値とテスト実行時間によって処理を切り分けているようで

	while ( config.queue.length && !config.blocking ) {
		if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) {
			config.queue.shift()();
		} else {
			window.setTimeout( process, 13 );
			break;
		}
	}

十分に大きな値にしておくか、0以下にしておけば時間のかかるテストのときに問題が起こらなくなる…らしい。けど下の"setTimeout(process, 13)"ってなんだ…?マジックナンバー。。

蛇足

最初「時間がかかるテスト」がよくわからず

require('../test_helper.js');

QUnit.test('hoge', function() {
    setTimeout(function() {
        assert.ok(true);
    }, 1000);
});

QUnit.start();

のようなのを書いていて「updateRateを設定しても動きません ><」となっていたんですが、QUnitで非同期のテストを書く場合はQUnit#stop と QUnit#start の組み合わせや、 QUnit#asyncTest を使うそうです。

require('../test_helper.js');

QUnit.asyncTest('hoge', function() {
    setTimeout(function() {
        assert.ok(true);
        QUnit.start();
    }, 1000);
});

QUnit.test('fuga' , function() {
    QUnit.stop(200);
    setTimeout(function() {
        assert.ok(true);
        QUnit.start();
    }, 100);
});

QUnit.start();

ちゃんとQUnitのドキュメント( http://docs.jquery.com/QUnit/asyncTest あたり? )とか読むべきですね。