Mocha не поддерживает то, что вы хотите сделать, просто установив флаг. Ближе всего использовать 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...
}
});
Если так получилось, что a
— это массив нулевой длины, то вы ничего не проверите, и тест пройдёт. В таких случаях я проверяю, что массив не имеет нулевой длины, но все же...
Таким образом, нет прямого способа сделать это, и Mocha не предлагает API для библиотек утверждений, к которым можно подключиться, чтобы сообщить Mocha, что они действительно использовались в тесте. Однако вы можете создать собственное решение. Вот доказательство концепции:
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
или истечет время ожидания. Вы можете иметь код из двух тестов, выполняющихся одновременно, если время предыдущего теста истекло, и так получилось, что тест, время ожидания которого истекло, фактически ожидало асинхронной операции, которая завершается по истечении тайм-аута. В таком случае, если есть какое-либо состояние, от которого зависят оба теста, тайм-аут может привести к каскадным ошибкам тестов (или каскадным успешным тестам!). Это общая проблема с 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
как this.expect
, что означает написание тестов не так, как обычно. Вы можете подумать, что установка глобального expect
перед каждым тестом избавит от необходимости использовать this
, но этот подход будет подвержен точно той же проблеме, о которой я говорил выше. (Глобальное состояние, совместно используемое тестами, будет само expect
вместо expect_called
.)
person
Louis
schedule
22.06.2015