Запуск установки Mocha перед каждым пакетом, а не перед каждым тестированием

Использование NodeJS и Mocha для тестирования. Кажется, я понимаю, как работают before() и beforeEach(). Проблема в том, что я хотел бы добавить setup script, который запускается перед каждым "описать", а не перед каждым "им".

Если я использую before(), он будет запускаться только один раз для всего пакета, и если я использую beforeEach(), он будет выполняться перед каждым отдельным тестом, поэтому я пытаюсь найти промежуточную точку.

Итак, если это мой тестовый файл:

require('./setupStuff');

describe('Suite one', function(){
  it('S1 Test one', function(done){
    ...
  });
  it('S1 Test two', function(done){
    ...
  });
});
describe('Suite two', function(){
  it('S2 Test one', function(done){
    ...
  });
});

Я хотел бы, чтобы "setupStuff" содержал функцию, которая работает до "Suite one" и "Suite two"

Или, другими словами, перед "S1 Test one" и "S2 Test one", но НЕ перед "S1 Test two".

Можно ли это сделать?

Ответ 1

Нет вызова, подобного beforeEach или before, который делает то, что вы хотите. Но это не нужно, потому что вы можете сделать это следующим образом:

function makeSuite(name, tests) {
    describe(name, function () {
        before(function () {
            console.log("shared before");
        });
        tests();
        after(function () {
            console.log("shared after");
        });
    });
}

makeSuite('Suite one', function(){
  it('S1 Test one', function(done){
      done();
  });
  it('S1 Test two', function(done){
      done();
  });
});

makeSuite('Suite two', function(){
  it('S2 Test one', function(done){
    done();
  });
});

Ответ 2

вы также можете сделать это более гибким способом:

require('./setupStuff');

describe('Suite one', function(){
  loadBeforeAndAfter(); //<-- added
  it('S1 Test one', function(done){
    ...
  });
  it('S1 Test two', function(done){
    ...
  });
});
describe('Suite two', function(){
  loadBeforeAndAfter();//<-- added
  it('S2 Test one', function(done){
    ...
  });
});
describe('Suite three', function(){
  //use some other loader here, before/after, or nothing
  it('S3 Test one', function(done){
    ...
  });
});

function loadBeforeAndAfter() {
  before(function () {
    console.log("shared before");
  });
  after(function () {
    console.log("shared after");
  });
}

Ответ 3

Я нашел, что этот подход работал у меня, он исправляет все описания наборов.

function suitePatches()
{
    before(function()
    {
        // before suite behaviour
    });
    after(function()
    {
        // after suite behaviour
    });
}

let origDescribe = describe;
describe = function(n,tests)
{
    origDescribe(n,function()
    {
        suitePatches();
        tests.bind(this)();
    });
}
let origOnly = origDescribe.only;
describe.only = function(n,tests)
{
    origOnly(n,function()
    {
        suitePatches();
        tests.bind(this)();
    });
}
describe.skip = origDescribe.skip;

Отличия от других ответов:

  • Использование bind для вызова tests, которое гарантирует, что если они вызовут функции на this, такие как this.timeout(1000), все равно будут работать.
  • Обработка .skip и .only означает, что вы все равно можете использовать их в своем пакете, например describe.skip, чтобы временно отключить пакеты.
  • Замена функции describe по имени позволяет использовать менее интрузивные инъекции.
    • Это может быть не каждый вкус, и в этом случае, очевидно, можно использовать альтернативное имя функции, но при этом использовать правильную обработку вызовов tests и only и skip.

Ответ 4

@ya_dimon решения работает, но если вы хотите, чтобы обернуть callback функции it, и передать параметр к нему как следует.

function dynamicTestCase(a) {
  return function(done){ console.log(a); } // a is undefined
}

describe("test", function(){
    before(function(){
        a = 8;
    });
    it('POST /verifications receiveCode', dynamicTestCase(a)); // a is undefined
})

Почему определяется? a Потому it это выполняется раньше, before в describe. В этом случае решение @ya_dimon не может работать, но вы можете сделать это хитро, как показано ниже.

function dynamicTestCase(a) {
  return function(done){ console.log(a()); } // a is delayed pass! a = 8, remember change a to a()
}

describe("test", function(){
    before(function(){
        a = 8;
    });
    it('POST /verifications receiveCode', dynamicTestCase(() => a)); // a is delayed pass!
})

Надеюсь, что это поможет выяснить последовательность выполнения.