Мокко не поддерживает то, что вы хотите сделать, просто установив флажок. Ближе всего использовать 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
является массивом из 0 длины, то вы не будете проверить что-нибудь, и тест пройдет. В таких случаях, как этот, я проверяю, что массив не является 0-длиной, но все же ...
Таким образом, нет прямого способа сделать это, и 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
.)