Mocha: рдиреЗрд╕реНрдЯреЗрдб рд╕реБрдЗрдЯреНрд╕/рд╕рдВрджрд░реНрднреЛрдВ рдореЗрдВ `рдкрд╣рд▓реЗ рдкреНрд░рддреНрдпреЗрдХ` рдФрд░ `рдЖрдлреНрдЯрд░рдПрдЪ` рдЪрд▓ рд░рд╣реЗ рд╣реИрдВ

рдХреЛ рдирд┐рд░реНрдорд┐рдд 28 рдЬреВрди 2013  ┬╖  17рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: mochajs/mocha

_рдЬрдм_ рдкрд░ рдХреЛрдИ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдирд╣реАрдВ рд╣реИ рдПрдХ beforeEach рдпрд╛ afterEach рдЪрд▓реЗрдЧрд╛ред рдореЗрд░рд╛ рдЕрдВрддрд░реНрдЬреНрдЮрд╛рди рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдЗрд╕реЗ рд╡рд░реНрддрдорд╛рди рд╕рдВрджрд░реНрдн рдореЗрдВ before / after рдкреНрд░рддреНрдпреЗрдХ describe / it рдмреНрд▓реЙрдХ рдореЗрдВ рдЪрд▓рд╛рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред

рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореИрдВ рдЬреЛ рд╡реНрдпрд╡рд╣рд╛рд░ рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдВ, рд╡рд╣ рдпрд╣ рд╣реИ рдХрд┐ beforeEach рдФрд░ afterEach рд╡рд░реНрддрдорд╛рди рд╕рдВрджрд░реНрдн рдореЗрдВ before / after _every_ it рдмреНрд▓реЙрдХ рдЪрд▓рд╛рдП рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рд╕рднреА рдиреЗрд╕реНрдЯреЗрдб рд╕рдВрджрд░реНрднред

рдореИрдВрдиреЗ рдпрд╣ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрд╡рдзрд╛рд░рдгрд╛ рдХрд╛ рдкреНрд░рдорд╛рдг рдмрдирд╛рдпрд╛ рд╣реИ рдХрд┐ рджреЗрдЦрд╛ рдЧрдпрд╛ рд╡реНрдпрд╡рд╣рд╛рд░ рд╣реЛ рд░рд╣рд╛ рд╣реИ: https://gist.github.com/twolfson/5883057#file -test-js

рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, рдореИрдВ рдпрд╣рд╛рдВ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдХреЙрдкреА/рдкреЗрд╕реНрдЯ рдХрд░реВрдВрдЧрд╛:

рд▓рд┐рдкрд┐

describe('An afterEach hook', function () {
  afterEach(function () {
    console.log('afterEach run!');
  });

  before(function () {
    console.log('before run!');
  });

  describe('in some nested contexts', function () {
    before(function () {
      console.log('nested before run!');
    });

    it('runs after this block', function () {
      console.log('nested it run!');

    });

    it('runs again after this block', function () {
      console.log('second nested it run!');
    });
  });
});

рдЙрддреНрдкрд╛рджрди

before run!
nested before run!
nested it run!
afterEach run!
second nested it run!
afterEach run!

рд╡реНрдпрд╡рд╣рд╛рд░ рдореИрдВ рд╕рд╣рдЬ рдЖрд╢рд╛ рд╣реИ afterEach рдХреЗ рдмрд╛рдж, рдПрдХ рдмрд╛рд░ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП second nested it ред

before run!
nested before run!
nested it run!
second nested it run!
afterEach run!

рд╕рд╣рдЬ рдЬреНрдЮрд╛рди рдпреБрдХреНрдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЗ рд▓рд┐рдП рдореЗрд░рд╛ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рдПрдХ рд╕рдВрджрд░реНрдн рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж this рд╕рдВрджрд░реНрдн рдХреЛ рд╕рд╛рдл рдХрд░ рд░рд╣рд╛ рд╣реИред рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкреНрд░рддреНрдпреЗрдХ рджрд╛рд╡реЗ рдХреЗ рдмрд╛рдж рд╕рдВрджрд░реНрдн рдХреЛ рд╕рд╛рдл рдХрд░ рджреЗрдЧрд╛ред

afterEach(function () {
  var key;
  for (key in this) {
    delete this[key];
  }
});

describe('A banana', function () {
  before(function () {
    this.banana = new Banana();
  });

  describe('when peeled', function () {
    before(function () {
      this.peeledBanana = this.banana.peel();
    });

    it('is white', function () {
      assert.strictEqual(this.peeledBanana.color, 'white');
      // `afterEach` is invoked here, cleaning out `this`
    });

    it('is soft', function () {
      // `this.peeledBanana` is no longer defined since `afterEach` cleaned it out
      assert.strictEqual(this.peeledBanana.hardness, 'soft');
    });
  });
});

рдЗрд╕рдХрд╛ рдПрдХ рддреБрд▓рдиреАрдп рдЙрджрд╛рд╣рд░рдг рдПрдХ рдкрд░реАрдХреНрд╖рдг рд╕реВрдЯ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдирдП рд╕рдВрджрд░реНрдн рдореЗрдВ рдПрдХ рдбреЗрдЯрд╛рдмреЗрд╕ рд▓реЗрдирджреЗрди рдЦреЛрд▓рдирд╛ рд╣реЛрдЧрд╛ред

рдореИрдВ рдкреНрд░рддреНрдпреЗрдХ рдиреЗрд╕реНрдЯреЗрдб рд╕рдВрджрд░реНрдн рдореЗрдВ after рдХрд╛ рдЖрд╣реНрд╡рд╛рди рдХрд░рдХреЗ рдЗрд╕рдХреЗ рдЖрд╕рдкрд╛рд╕ рдХрд╛рдо рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдврд╛рдВрдЪреЗ рдореЗрдВ рдПрдХ рд╣реБрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдЗрд╕ рд╕рд╛рдорд╛рдиреНрдп рдкрд░рд┐рджреГрд╢реНрдп рд╡рд╛рд▓реЗ рд╕рднреА рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдпрд╣ рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдпрд╛ рд╣реИ рдЬреЛ рд╡рд░реНрддрдорд╛рди рдмреНрд▓реЙрдХ рдореЗрдВ рд╕рднреА рд╕реБрдЗрдЯреНрд╕ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдП beforeAll рд╣реБрдХ рдЬреЛрдбрд╝рддрд╛ рд╣реИ:

function beforeEachSuite (fn) {
  before(function () {
    let suites = this.test.parent.suites || []
    suites.forEach(s => {
      s.beforeAll(fn)
      let hook = s._beforeAll.pop()
      s._beforeAll.unshift(hook)
    })
  })
}

рдпрд╣ рд▓рдЧрднрдЧ рдПрдХ рд╕рд╛рд▓ рдкрд╣рд▓реЗ рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ рд╡рд░реНрдгрд┐рдд рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЛ рдЕрдирд▓реЙрдХ рдХрд░рддрд╛ рд╣реИ:

describe('Create Article', () => {
  beforeEachSuite(() => console.log('CLEAN DB'))

  context('When Article is valid', () => {
    before(() => console.log("INSERTING VALID ARTICLE"))

    it('should not fail')
    it('should have some properties')    
    it('should send an email')  
  })

  context('When Article is not valid', () => {
    before(() => console.log("INSERTING NOT VALID ARTICLE"))

    it('should fail')
    it('should not send an email')  
  })
})

рдЕрднреА рднреА рдпрд╣ рдирд╣реАрдВ рдорд┐рд▓рддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЛ рдЙрдкрдпреЛрдЧреА рдпрд╛ рд╡реИрдз рдХреНрдпреЛрдВ рдирд╣реАрдВ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред
рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рд╕рдорд╛рдзрд╛рди рдХреЛ beforeEachSuite рдФрд░ afterEachSuite рдкреАрдЖрд░ рдореЗрдВ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХреЗ

рд╕рднреА 17 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдЬрд┐рдЬреНрдЮрд╛рд╕реБ рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдореЗрд░реЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХрд╛ рд╕рдорд╛рдзрд╛рди рд╣реИ:

// Before anything else is run
before(function () {
  // Iterate over all of the test suites/contexts
  this.test.parent.suites.forEach(function bindCleanup (suite) {
    // Attach an afterAll listener that performs the cleanup
    suite.afterAll(function cleanupContext () {
      var key;
      for (key in this) {
        delete this[key];
      }
    });
  });
});

+1

afterEach рдкреНрд░рддреНрдпреЗрдХ Runnable рдЙрджрд╛рд╣рд░рдг рдХреЗ рдмрд╛рдж рдЪрд▓рддрд╛ рд╣реИ; рдЖрдкрдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдПрдХ it() рдмреНрд▓реЙрдХред рдпрджрд┐ рдЖрдк рдиреЗрд╕реНрдЯреЗрдб рд╡реНрдпрд╡рд╣рд╛рд░ рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рдиреЗрд╕реНрдЯ рди рдХрд░реЗрдВред рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдмрджрд▓рдирд╛ рдореЗрдЬ рдкрд░ рдирд╣реАрдВ рд╣реИред

рдпрджрд┐ рдЖрдкрдХрд╛ рджреВрд╕рд░рд╛ рдкрд░реАрдХреНрд╖рдг рдЖрдкрдХреЗ рдкрд╣рд▓реЗ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рд╕реА рдЪреАрдЬрд╝ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рддреЛ рдЖрдкрдХреЗ рдкрд░реАрдХреНрд╖рдг рдЧрдВрджреЗ рд╣реИрдВ рдФрд░ рдЖрдк рдЗрд╕реЗ рдЧрд▓рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЬрд┐рд╕ рдХреНрд░рдо рдореЗрдВ рдЖрдкрдХреЗ рдкрд░реАрдХреНрд╖рдг рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрддреЗ рд╣реИрдВ, рдЙрд╕рд╕реЗ рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ред рддрджрдиреБрд╕рд╛рд░ рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦреЗрдВ, рдФрд░ рд╡реЗ рдЕрдзрд┐рдХ рдореВрд▓реНрдпрд╡рд╛рди рд╣реЛрдВрдЧреЗред

рд╕рд╛рде рд╣реА, this 90% рд╕рдордп рдкрд░ рдХреБрдЫ рднреА рдбрд╛рд▓рдирд╛ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИред

describe('A banana', function () {
  var banana;

  before(function () {
    banana = new Banana();
  });

  describe('when peeled', function () {
    var peeledBanana;

    beforeEach(function () {
      // I'm assuming peel() has no side-effects since it returns a new object.
      peeledBanana = banana.peel();
    });

    it('is white', function () {
      assert.strictEqual(peeledBanana.color, 'white');
    });

    it('is soft', function () {
      assert.strictEqual(peeledBanana.hardness, 'soft');
    });
  });
});

рдХреНрдпрд╛ рдЗрд╕рдХреЗ () рд╕реНрддрд░ рдХреЗ рдмрдЬрд╛рдп рд╡рд░реНрдгрди () рд╕реНрддрд░ рдореЗрдВ рд╣реБрдХ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рд╣реИ? рдпрд╣ рдХреБрдЫ рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдореЗрдВ рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

@RathaKM рдЙрдкрдпреЛрдЧ рдХрд╛ рдорд╛рдорд▓рд╛ рдХреНрдпрд╛ рд╣реИ?

рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрджрд╛рд╣рд░рдг рд╣реИ, рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рд╣реЛрдЧрд╛? @RathaKM рд╕рд╣реА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рдорд╣рд╕реВрд╕ рдХрд░реЗрдВред

describe('A banana', function () {
  var banana;

  beforeEach(function () {
    banana = new Banana();
  });

  describe('when peeled', function () {
    var peeledBanana;

    before(function () {
      // Lets assume peel() HAS side-effects and doesn't return a new object.
      banana.peel();
      peeledBanana = banana;
    });

    it('is white', function () {
      assert.strictEqual(peeledBanana.color, 'white');
    });

    it('is soft', function () {
      assert.strictEqual(peeledBanana.hardness, 'soft');
    });
  });

  describe('when set on FIRE', function () {
    var flamingBanana;

    before(function () {
      // Same assumption as above
      banana.setOnFire();
      flamingBanana = banana
    });

    it('is hot', function () {
      assert.isAbove(flamingBanana.temperature, 9000);
    });
  });
});

@cpoonolly : рдЖрдкрдХреА рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж рдФрд░ рдЗрд╕реЗ рд╡рд╛рдкрд╕ рд▓рд╛рдПрдВред :) рдЖрдкрдХрд╛ рдЙрджрд╛рд╣рд░рдг рд╡рд╣ рд╣реИ рдЬреЛ рддрд╛рд░реНрдХрд┐рдХ рд░реВрдк рд╕реЗ рд╡рд░реНрдгрди рд╕реНрддрд░ (рдкрд╣рд▓реЗ рд╕реЗ) рдореЗрдВ рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди, рдпрд╣ рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рд╡рд░рдг рдХреЗ рднреАрддрд░ 'рдкрд╣рд▓реЗ ()' рдХреЗ рд╕рд╛рде рд╣рд╛рд╕рд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдореИрдВ рдЬрд┐рд╕ рдореБрджреНрджреЗ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░ рд░рд╣рд╛ рдерд╛ рд╡рд╣ рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

var testData = [{country: 'NIL'}],
dataDriven = require('data-driven'),
assert = require('assert');

describe('@Testing_For_Describe_Level_Hook_Method_To_Update_TestData@', function () {

    describe('<strong i="8">@Updated</strong> testData for US@', function () {
        before(function (done) {
            testData = [{country: 'US'}];
            done();
        });
        dataDriven(testData, function () {
            it('expecting updated testData for US', function (ctx, done) {
                assert.equal(ctx.country, 'US');
                done();
            });
        });
    });

    describe('<strong i="9">@Updated</strong> testData for UK@', function () {
        before(function (done) {
            testData = [{country: 'UK'}];
            done();
        });
        dataDriven(testData, function () {
            it('expecting updated testData for UK', function (ctx, done) {
                assert.equal(ctx.country, 'UK');
                done();
            });
        });
    });
});

рдпрд╣рд╛рдВ, рдкрд░реАрдХреНрд╖рдг рд╕реВрдЯ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред рд╣рдо _testData_ рдХреЛ 'рдкрд╣рд▓реЗ ()' рд╣реБрдХ рд╡рд┐рдзрд┐ рдХреЗ рднреАрддрд░ рдЕрдкрдбреЗрдЯ рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ '_it_' рдмреНрд▓реЙрдХ рд╕реЗ рдареАрдХ рдкрд╣рд▓реЗ рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ред рд▓реЗрдХрд┐рди, рд╣рдо _dataDriven()_ рдХреЗ рднреАрддрд░ _testData_ рд╡реЗрд░рд┐рдПрдмрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ '_it_' рдмреНрд▓реЙрдХ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

рдЗрд╕рд▓рд┐рдП, рд╣рдореЗрдВ рдпрд╣рд╛рдВ _'it'_ рдмреНрд▓реЙрдХ рдирд┐рд╖реНрдкрд╛рджрди рд╢реБрд░реВ рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╡реЗрд░рд┐рдПрдмрд▓ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЬрдЧрд╣ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╣рдореЗрдВ 'рдбрд┐рд╕реНрдХреНрд░рд╛рдЗрдм' рдмреНрд▓реЙрдХ (рдбрд┐рд╕реНрдХреНрд░рд╛рдЗрдм рд▓реЗрд╡рд▓ рд╣реБрдХ рдореЗрдердб) рд╕реЗ рдареАрдХ рдкрд╣рд▓реЗ _before()_ рд╣реБрдХ рдореЗрдердб рдПрдХреНрдЬреАрдХреНрдпреВрд╢рди рдХреА рдЬрд░реВрд░рдд рд╣реЛред

рдЖрд╢рд╛ рд╣реИ, рдЕрдм рдорд╛рдорд▓рд╛ рд╕реНрдкрд╖реНрдЯ рд╣реЛ рдЧрдпрд╛ рд╣реИред

рдХреНтАНрдпрд╛ рдЗрд╕ рдкрд░ рдХреЛрдИ рдЕрддрд┐рд░рд┐рдХреНтАНрдд рдЪрд░реНрдЪрд╛ рд╣реБрдИ рд╣реИ?

рдРрд╕рд╛ рдХреБрдЫ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдХреНрдпреЛрдВ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИ?

describe('Create Article', () => {
  beforeEach(() => console.log('CLEAN DB'))

  context('When Article is valid', () => {
    before(() => console.log("INSERTING VALID ARTICLE"))

    it('should not fail')
    it('should have some properties')    
    it('should send an email')  
  })

  context('When Article is not valid', () => {
    before(() => console.log("INSERTING NOT VALID ARTICLE"))

    it('should fail')
    it('should not send an email')  
  })
})
  • рдкреНрд░рддреНрдпреЗрдХ context рдмреНрд▓реЙрдХ рд╕реЗ рдкрд╣рд▓реЗ DB рдХреЛ рд╕рд╛рдл рдХрд░реЗрдВред
  • рд╕рднреА it рдмреНрд▓реЙрдХ рд╕реЗ рдкрд╣рд▓реЗ рдкрд░рд┐рджреГрд╢реНрдп рд╕реЗрдЯ рдХрд░реЗрдВ

рдХреНрдпрд╛ рдпрд╣ рдХрд╛рдиреВрдиреА рдЙрдкрдпреЛрдЧ рдХрд╛ рдорд╛рдорд▓рд╛ рдирд╣реАрдВ рд╣реИ?

@ marqu3z рдореИрдВ рдЖрдкрдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХрд╛ рдкрд╛рд▓рди рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред рдпрд╣ рд╡реИрдз рд╣реИред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ: рдкрд╣рд▓реЗ рд╡рд╛рд▓рд╛ рд╣реБрдХ рдкрд╣рд▓реЗ рдХреЗ рд╣реБрдХ рд╕реЗ рдкрд╣рд▓реЗ рдЪрд▓рддрд╛ рд╣реИ? рд▓реЗрдХрд┐рди рдЖрдкрдХреЛ рдкрд╣рд▓реЗ рд╡рд╛рд▓реЗ рд╣реБрдХ рдХреЗ рдмрд╛рдж рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реЗ рд╣реБрдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ?

(рдХреНрдпрд╛ рдЖрдк рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдЯреЗрд╕реНрдЯ рдХреЗрд╕ рдХреЗ рд▓рд┐рдП рдбреАрдмреА рдХреЛ рд╕рд╛рдл рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ? рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХреЗрд╡рд▓ рдЖрдкрдХрд╛ рдкрд╣рд▓рд╛ рдЯреЗрд╕реНрдЯ рдХреЗрд╕ рд╣реА рд╕рдлрд▓ рд╣реЛрдЧрд╛, рдЕрдиреНрдп рдХреЗ рдкрд╛рд╕ рдХреЛрдИ рдбреЗрдЯрд╛ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рд▓реЗрдХрд┐рди рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдк рдкреНрд░рддреНрдпреЗрдХ рдЯреЗрд╕реНрдЯ рдХреЗрд╕ рдХреЗ рд▓рд┐рдП рдбреАрдмреА рдХреЛ рд╕рд╛рдл рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ)ред

рдореЛрдЪрд╛ рджрд┐рдП рдЧрдП рдЖрдкрдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рдореЗрд░реЗ рджреЛ рдкреНрд░рдпрд╛рд╕ рдпрд╣рд╛рдВ рджрд┐рдП рдЧрдП рд╣реИрдВ:

(1) рдкрд╣рд▓реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ, рд▓реЗрдХрд┐рди рдПрдХ рдмреВрд▓рд┐рдпрди рдлреНрд▓рд┐рдк рдХрд░реЗрдВ, рдЗрд╕рд▓рд┐рдП рдкрд╣рд▓реЗ рд╡рд╛рд▓рд╛ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдЪрд▓рддрд╛ рд╣реИ (рдпрд╣ рдереЛрдбрд╝реЗ рдмреЗрдХрд╛рд░ рд╣реИ)

describe('Create Article', () => {
  beforeEach(() => console.log('CLEAN DB'))

  context('When Article is valid', () => {
    let flip = true;
    beforeEach(() => flip && (flip = false; console.log('INSERTING VALID ARTICLE')))

    it('should not fail')
    it('should have some properties')    
    it('should send an email')  
  })

  context('When Article is not valid', () => {
   let flip = true;
    beforeEach(() => flip && (flip = false; console.log('INSERTING NOT VALID ARTICLE')))

    it('should fail')
    it('should not send an email')  
  })
})

(2) рдРрд╕рд╛ рдХрд░рдиреЗ рдХрд╛ рджреВрд╕рд░рд╛ рддрд░реАрдХрд╛ - рдпрд╣ рдЬреНрдпрд╛рджрд╛ рдмреЗрд╣рддрд░ рдирд╣реАрдВ рд╣реИ!

describe('Create Article', () => {

  let cleanDB = function(fn){
    return function(done){
        actuallyCleanDB(function(err){
            if(err) return done(err);
            fn(done);
       });
    }
  };

  context('When Article is valid', () => {
    before(() => console.log('INSERTING VALID ARTICLE'))
    it('should not fail', cleanDB(function(done){})
    it('should have some properties', cleanDB(function(done){}))    
    it('should send an email', cleanDB(function(done){})) 
  })

  context('When Article is not valid', () => {
    before(() => console.log('INSERTING NOT VALID ARTICLE')))
    it('should fail', cleanDB(function(done){}))
    it('should not send an email',cleanDB(function(done){}))  
  })
})

рдХреГрдкрдпрд╛ рдореБрдЭреЗ рдмрддрд╛рдПрдВ рдХрд┐ рдХреНрдпрд╛ рдореИрдВ рдЖрдкрдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╕рдордЭрддрд╛ рд╣реВрдВ, рдФрд░ рдореИрдВ рд╕рдорд╛рдзрд╛рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рдЪрдХреНрд░ рдмрд┐рддрд╛рдКрдВрдЧрд╛ред рдореЗрд░рд╛ рдХреЛрдИ рднреА рд╕рдорд╛рдзрд╛рди рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рдХреЗрд╡рд▓ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдореИрдВ рдЖрдкрдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╕рдордЭреВрдВред

@RathaKM

рдХреНрдпрд╛ рдЖрдк рдЕрдкрдиреЗ it() рдкрд░реАрдХреНрд╖рдг рдорд╛рдорд▓реЛрдВ рдХреЛ рдЕрддреБрд▓реНрдпрдХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдкрдВрдЬреАрдХреГрдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ? рдпрджрд┐ рдРрд╕рд╛ рд╣реИ рддреЛ рдЗрд╕рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рд╣реИред рдЖрдкрдХреЛ describe/after/afterEach/before/beforeEach рд╕рднреА рд╕рдордХрд╛рд▓рд┐рдХ рд░реВрдк рд╕реЗ рдкрдВрдЬреАрдХреГрдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред

// event loop tick X
 dataDriven(testData, function () {
     // it() must be called in the same event loop tick as X above
        it('expecting updated testData for UK', function (ctx, done) {
            assert.equal(ctx.country, 'UK');
            done();
       });
  });

рднреА, ctx рдХрд╣рд╛рдБ рд╕реЗ рдЖ рд░рд╣рд╛ рд╣реИ? рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдореИрдВ рдирд╡реАрдирддрдо рдореЛрдЪрд╛ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдкрд░ рдЕрдк-рдЯреВ-рдбреЗрдЯ рдирд╣реАрдВ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдХрднреА рдирд╣реАрдВ рджреЗрдЦрд╛

it(foo, function(ctx, done){
   // where is ctx coming from?
});

рдореИрдВ рдареАрдХ рдЙрд╕реА рдкрд░рд┐рджреГрд╢реНрдп рдореЗрдВ рд╣реВрдВ @ marqu3z рд╡рд░реНрдгрд┐рдд рд╣реИред describe рд╕реНрддрд░ beforeEach рд▓рд┐рдП рд╕рдорд░реНрдерди рджреЗрдЦрдирд╛ рдкрд╕рдВрдж рдХрд░реЗрдВрдЧреЗ

рдЗрд╕ рд╕рд╛рдорд╛рдиреНрдп рдкрд░рд┐рджреГрд╢реНрдп рд╡рд╛рд▓реЗ рд╕рднреА рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдпрд╣ рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдпрд╛ рд╣реИ рдЬреЛ рд╡рд░реНрддрдорд╛рди рдмреНрд▓реЙрдХ рдореЗрдВ рд╕рднреА рд╕реБрдЗрдЯреНрд╕ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдП beforeAll рд╣реБрдХ рдЬреЛрдбрд╝рддрд╛ рд╣реИ:

function beforeEachSuite (fn) {
  before(function () {
    let suites = this.test.parent.suites || []
    suites.forEach(s => {
      s.beforeAll(fn)
      let hook = s._beforeAll.pop()
      s._beforeAll.unshift(hook)
    })
  })
}

рдпрд╣ рд▓рдЧрднрдЧ рдПрдХ рд╕рд╛рд▓ рдкрд╣рд▓реЗ рдореЗрд░реЗ рджреНрд╡рд╛рд░рд╛ рд╡рд░реНрдгрд┐рдд рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЛ рдЕрдирд▓реЙрдХ рдХрд░рддрд╛ рд╣реИ:

describe('Create Article', () => {
  beforeEachSuite(() => console.log('CLEAN DB'))

  context('When Article is valid', () => {
    before(() => console.log("INSERTING VALID ARTICLE"))

    it('should not fail')
    it('should have some properties')    
    it('should send an email')  
  })

  context('When Article is not valid', () => {
    before(() => console.log("INSERTING NOT VALID ARTICLE"))

    it('should fail')
    it('should not send an email')  
  })
})

рдЕрднреА рднреА рдпрд╣ рдирд╣реАрдВ рдорд┐рд▓рддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рдХреЛ рдЙрдкрдпреЛрдЧреА рдпрд╛ рд╡реИрдз рдХреНрдпреЛрдВ рдирд╣реАрдВ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред
рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рд╕рдорд╛рдзрд╛рди рдХреЛ beforeEachSuite рдФрд░ afterEachSuite рдкреАрдЖрд░ рдореЗрдВ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХреЗ

рд╣рд╛рдБ рдХреГрдкрдпрд╛ рд╣рдореЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

https://github.com/mochajs/mocha/issues/911#issuecomment -316736991 рдЬреИрд╕реЗ рдХрдИ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рд╣реИрдВ

+1

+1

рдореИрдВ рдЗрд╕ рдзрд╛рдЧреЗ рдкрд░ рдХреБрдЫ рдЗрд╕реА рддрд░рд╣ рдХреА рддрд▓рд╛рд╢ рдореЗрдВ рдареЛрдХрд░ рдЦрд╛рдИред рддреЛ рдЗрд╕ рдкреЛрд╕реНрдЯ рдкрд░ рдареЛрдХрд░ рдЦрд╛рдиреЗ рд╡рд╛рд▓реЗ рдХрд┐рд╕реА рдФрд░ рдХреЗ рд▓рд┐рдП ...

рдореИрдВрдиреЗ рдЙрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд┐рдпрд╛ рд╣реИ рдЬрд┐рд╕реЗ @marqu3z рдиреЗ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдПрдирдкреАрдПрдо рдкреИрдХреЗрдЬ рдореЗрдВ рдЙрд▓реНрд▓рд┐рдЦрд┐рдд рдХрд┐рдпрд╛ рд╣реИ: mocha-suite-hooks ред

рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдЖрдк рд╕реНрд╡рдпрдВ рдХреЛ рдРрд╕реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдкрд╛рддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ before рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИ, рдФрд░ beforeEach рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╣реИ, рддреЛ beforeSuite рдЖрдЬрд╝рдорд╛рдПрдВред

рдкреИрдХреЗрдЬ рдЕрднреА рднреА рдмрд╣реБрдд рдХрдЪреНрдЪрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдХрд┐рд╕реА рднреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рдмрд╣реБрдд рд╕рд░рд╛рд╣рдирд╛ рдХреА рдЬрд╛рдПрдЧреА!

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

enigmatic00 picture enigmatic00  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

jamietre picture jamietre  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

jmiller-airfox picture jmiller-airfox  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

smithamax picture smithamax  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

danielserrao picture danielserrao  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ