モカはフラグを立てただけではやりたいことをサポートしてくれません。最も近いのはit
、コールバックなしで使用することです:
`it("foo")`
Mocha はこのテストを扱い、pending
そのように報告します。を使用するのと同じit.skip(...)
です。ただし、テストは失敗せず、実際には繰り返されないループがあるなどの愚かな間違いを検出しません。
it("foo", function () {
var a = something();
for (var i = 0; i < a.length; ++i) {
expect(a[i]).to...
}
});
長さ 0 の配列が発生した場合a
は、何もテストせず、テストに合格します。このような場合、配列の長さが 0 ではないことをテストしますが、それでも...
したがって、それを行う直接的な方法はなく、Mocha はアサーション ライブラリがフックして、テストで実際に使用されたことを Mocha に伝えるための API を提供していません。ただし、独自のソリューションを構築できます。概念実証は次のとおりです。
var real_expect = require("chai").expect;
var expect_called = 0;
function expect() {
expect_called++;
return real_expect.apply(this, arguments);
}
var real_it = it;
it = function (name, fn) {
if (!fn.length) {
// Handle the case where `fn` is declared to be synchronous.
real_it(name, function () {
expect_called = 0;
fn.call(this);
if (expect_called === 0)
throw new Error("test did not call expect");
});
}
else {
// Handle the case where `fn` is declared to be asynchronous.
real_it(name, function (real_done) {
expect_called = 0;
function done () {
if (expect_called === 0) {
done(new Error("test did not call expect"));
return;
}
real_done();
}
fn.call(this, done);
});
}
};
it("foo", function () {
expect(1).to.equal(1);
});
it("foo async", function (done) {
setTimeout(function () {
expect(1).to.equal(1);
done();
}, 1000);
});
it("bar", function () {});
it("bar 2", function () {});
上記のコードit
では、チェックを行う独自のものに置き換えexpect
、呼び出されたときにフラグを立てるために独自のものに置き換えます。
非同期テストと共有状態に関するメモ。非同期としてマークされている場合、Mocha が同時に複数実行されると考える人がいます。通常、これは当てはまりません。Mocha は、非同期テストの後に続行する前に、テストがdone
コールバックを呼び出すか、タイムアウトするかのいずれかを待機します。前のテストがタイムアウトした場合、2 つのテストのコードを同時に実行することができ、タイムアウトしたテストが実際には後で完了する非同期操作を待っていた場合があります。タイムアウト。このような場合、両方のテストが依存する状態があると、タイムアウトにより、カスケード テストの失敗 (またはカスケード テストの成功!) が発生する可能性があります。これは Mocha の一般的な問題です。タイムアウトの問題が修正されると、カスケード効果がなくなり、タイムアウトした以前の非同期テストの影響を受けることなく、後続のテストが成功または失敗するようになります。上記のコードでexpected_called
は、すべてのテストが依存する状態です。そのため、タイムアウトはカスケード効果を引き起こす可能性があります。
この問題を解決するには、各テストに の独自のプライベート インスタンスが必要ですexpect
。これは、独自のプライベート カウンタをインクリメントするだけです。これは次のように行うことができます。
var real_expect = require("chai").expect;
var real_it = it;
it = function (name, fn) {
if (!fn.length) {
// Handle the case where `fn` is declared to be synchronous.
real_it(name, function () {
var expect_called = 0;
this.expect = function () {
expect_called++;
return real_expect.apply(this, arguments);
};
fn.call(this);
if (expect_called === 0)
throw new Error("test did not call expect");
});
}
else {
// Handle the case where `fn` is declared to be asynchronous.
real_it(name, function (real_done) {
var expect_called = 0;
this.expect = function () {
expect_called++;
return real_expect.apply(this, arguments);
};
function done () {
if (expect_called === 0) {
done(new Error("test did not call expect"));
return;
}
real_done();
}
fn.call(this, done);
});
}
};
it("foo", function () {
this.expect(1).to.equal(1);
});
it("foo async", function (done) {
var me = this;
setTimeout(function () {
me.expect(1).to.equal(1);
done();
}, 1000);
});
it("bar", function () {});
it("bar 2", function () {});
ただし、欠点は、expect
asにアクセスする必要があることですthis.expect
。これは、通常とは異なる方法でテストを作成することを意味します。すべてのテストの前にグローバルを設定するexpect
と使用する必要がなくなると思うかもしれませんthis
が、このアプローチは上で説明したのとまったく同じ問題の対象となります。(テストによって共有されるグローバルな状態は、expect
ではなくそれ自体になりexpect_called
ます。)