web-dev-qa-db-ja.com

各テストの前ではなく、各スイートの前にMochaセットアップを実行する

テストにNodeJSとMochaを使用する。 before()とbeforeEach()がどのように機能するか理解していると思います。問題は、各 "それ"の前ではなく、各 "説明"の前に実行するセットアップスクリプトを追加することです。

before()を使用すると、スイート全体で1回だけ実行されます。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」の前ではありません。

できますか?

25
FuzzyYellowBall

beforeEachbeforeのような、必要な呼び出しを行う呼び出しはありません。ただし、次の方法で実行できるため、必要ありません。

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();
  });
});
21
Louis

次のより柔軟な方法で行うこともできます。

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");
  });
}
10
ya_dimon

@ya_dimonのソリューションは機能していますが、callbackit関数をラップし、次のようにパラメーターを渡す場合は、.

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が定義されていないのですか? itbeforedescribeの前に実行されるためです。この場合、@ 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!
})

これが実行シーケンスを理解するのに役立つことを願っています。

0
Tokenyet

私はこのアプローチがうまくいくことを発見しました、それはすべてのスイートを説明するパッチを当てます。

_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関数を名前で置き換えると、煩わしさの少ない注入が可能になります。
    • これは誰の好みにもならない場合があります。その場合、testsonlyskipの呼び出しの正しい処理を利用しながら、代替関数名を使用できます。 。
0
tul