2015-06-22 4 views
4

Есть ли возможность установить mocha для сообщения теста как сбоя в случае отсутствия ожидаемого в нем функции()?Как сделать mocha неудачным, если в нем нет ожидаемого()

Идея рабочего процесса, чтобы быть похожим на это:

  1. добавьте его() с убыванию и обратного вызова функции
  2. в его(), как сообщается, как не в состоянии, так как никакого ожидания не устанавливается в обратном вызове
  3. ожидание добавляется
  4. его() по-прежнему сообщают, как терпит неудачу, поскольку ожидание не выполняется, так как не реализации добавляются
  5. реализации
  6. тем он() сообщается как успех
  7. рефакторинг

Так основная цель является при этом каноническим стилем TDD развивающегося вновь добавленного тест сообщаются несостоявшимися пока ожидания не установлено (или испытательная установки в ожидании без обратного вызова или пропустить()), который снова сообщается как сбой, и как только реализация выполнена, он считается успешным.

Значение, которое я вижу для него(), без ожидания, состоит в том, что после его добавления это отказ теперь доказывает, что он фактически работает и доказывает, что он терпит неудачу. Было ли это намерение или я что-то упускаю?

Кроме того, если у кого-нибудь есть идея, как установить, что в karma.conf.js было бы здорово.

Благодаря

ответ

1

Мокко не поддерживает то, что вы хотите сделать, просто установив флажок. Ближе всего использовать 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.)