javascript 在每个套件之前而不是在每个测试之前运行 Mocha 设置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26107027/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 05:31:03  来源:igfitidea点击:

Running Mocha setup before each suite rather than before each test

javascriptnode.jsmocha

提问by FuzzyYellowBall

Using NodeJS and Mocha for testing. I think I understand how before() and beforeEach() work. Problem is, I'd like to add a setup script that runs before each "describe" rather than before each "it".

使用 NodeJS 和 Mocha 进行测试。我想我明白 before() 和 beforeEach() 是如何工作的。问题是,我想添加一个在每个“描述”之前而不是在每个“它”之前运行的安装脚本。

If I use before()it will run only once for the entire suite, and if I use beforeEach()it will execute before every single test, so I'm trying to find a middle ground.

如果我使用before()它,整个套件只会运行一次,如果我使用beforeEach()它,它将在每次测试之前执行,所以我试图找到一个中间立场。

So, if this is my test file:

所以,如果这是我的测试文件:

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){
    ...
  });
});

I'd like to have "setupStuff" contain a function that runs before 'Suite one' and 'Suite two'

我想让“setupStuff”包含一个在“套件一”和“套件二”之前运行的函数

Or, in other words, before 'S1 Test one' and 'S2 Test one' but NOT before 'S1 Test two'.

或者,换句话说,在“S1 测试一”和“S2 测试一”之前,而不是“S1 测试二”之前。

Can it be done?

可以做到吗?

采纳答案by Louis

There's no call similar to beforeEachor beforethat does what you want. But it is not needed because you can do it this way:

没有类似于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();
  });
});

回答by ya_dimon

you can also do it in this more flexible way:

你也可以用这种更灵活的方式来做到这一点:

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

回答by tul

I have found this approach worked for me, it patches all describe suites.

我发现这种方法对我有用,它修补了所有描述套件。

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;

Differences from the other answers are:

与其他答案的不同之处在于:

  • The use of bindto call the testswhich ensures that if they call functions on this, such as this.timeout(1000)will still work.
  • Handling .skipand .onlymeans that you can still use those on your suite, eg describe.skipto temporarily suppress suites.
  • Replacing the describefunction by name allows for a less intrusive injection.
    • This may not be to everyone's taste, in which case obviously an alternative function name can be used whilst still making use of the correct handling of calling the testsand onlyand skip.
  • 使用bindto calltests确保如果他们调用函数 on this,例如this.timeout(1000)仍然可以工作。
  • 处理.skip.only意味着您仍然可以在您的套件中使用它们,例如describe.skip暂时取消套件。
  • describe按名称替换函数可以减少侵入性注入。
    • 这可能不是每个人的口味,在这种情况下,显然是一个别名功能名称可以同时仍利用的调用正确处理使用testsonlyskip

回答by Tokenyet

@ya_dimon 's solution is working, but If you want to wrap the callbackfunction of it, and pass parameter to it as follow.

@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
})

Why ais undefined? Because itis executed before beforein describe. In this case, @ya_dimon 's solution could not work, but you could make It done trickly as following.

为什么a是未定义的?因为it是在beforein之前执行的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!
})

Hope this help to figure out the execution sequence.

希望这有助于找出执行顺序。