Javascript 摩卡咖啡的目的是什么;s before()函数?

Javascript 摩卡咖啡的目的是什么;s before()函数?,javascript,unit-testing,mocha.js,Javascript,Unit Testing,Mocha.js,Mocha有几个“钩子”在一个独立于测试用例本身的测试中运行辅助功能(清除数据库、创建模拟文件等) 然而,在before()(不是beforeach(),我得到的那一个)的情况下,它似乎是多余的 before()在当前套件中的所有测试之前运行一次逻辑,那么为什么我甚至需要将其包装到函数中呢 以下两项之间没有明显差异: describe('Something', function() { before(doSomePreTestLogic); //Tests ahoy }); 及

Mocha有几个“钩子”在一个独立于测试用例本身的测试中运行辅助功能(清除数据库、创建模拟文件等)

然而,在
before()
不是
beforeach()
,我得到的那一个)的情况下,它似乎是多余的

before()
在当前套件中的所有测试之前运行一次逻辑,那么为什么我甚至需要将其包装到函数中呢

以下两项之间没有明显差异:

describe('Something', function() {
    before(doSomePreTestLogic);
    //Tests ahoy
});


before()
包装我的预测试逻辑有什么意义?

在机器和人的层面上的语义

此外,它使测试代码与“导出”接口保持一致,例如

module.exports = {
  before: function(){
    // ...
  },

  'Array': {
    '#indexOf()': {
      'should return -1 when not present': function(){
        [1,2,3].indexOf(4).should.equal(-1);
      }
    }
  }
};

在测试中选择
before()
钩子有两个不同的原因:

语义

这可能是最大的一个。有时,在运行实际测试之前,您可能需要执行一项任务,例如在数据库中填充一些虚拟数据。您当然可以在测试本身中这样做,但是如果您在预填充时遇到错误,并且在运行实际的测试用例之前,那么您的报告就会中断。通过使用
before()
钩子,可以在逻辑上、语义上有效地插入这种逻辑

异步测试的清理器

就像mocha测试可以是异步的一样,您的
before()
hook逻辑也可以是异步的。回到预填充示例,这很方便,因为这意味着所有异步预测试逻辑不会在所有实际测试逻辑上强制进行另一级别的缩进

与其他挂钩的一致性:

Mocha还提供了其他几个钩子,即:
after()
beforeach()
,和
afterEach()
。对于所有其他钩子,您可能也会问同样的问题,但是如果您相信其中任何一个钩子都有经过验证的存在,那么就需要包含
before()
来完善API。

结果是 直接放入将构建测试套件的
描述
回调代码中。我说的是对
it
的调用,但也包括一些函数,它们可以循环表或文件来声明一系列测试(通过在循环中调用
it

将实际初始化测试所依赖的状态的代码放入钩子中

所有其他考虑都是次要的

让我解释一下

背景 Mocha分两个阶段执行测试套件:

  • 它发现存在哪些测试。在此阶段,它将立即执行传递给
    descripe
    的回调,并记录传递给声明测试的函数(
    it
    等)和声明挂钩的函数(
    before
    beforeach
    after
    等)的回调,以备将来调用

  • 它运行测试。在这个阶段,它将运行它先前记录的回调

  • 区别 请考虑这个例子:

    function dump () { console.log("running:", this.test.fullTitle()); }
    describe("top", function () {
        before(dump);
        it("test 1", dump);
        it("test 2", dump);
        describe("level 1", function () {
            before(dump);
            it("test 1", dump);
            it("test 2", dump);
        });
    });
    
    请注意,
    fullTitle
    给出了一个测试的全名,从顶层
    descripe
    ,经过任何嵌套的
    descripe
    ,一直到
    it
    或包含调用的钩子。使用
    spec
    reporter运行,并仅保持
    运行:
    行,您将获得:

    running: top "before all" hook: dump
    running: top test 1
    running: top test 2
    running: top level 1 "before all" hook: dump
    running: top level 1 test 1
    running: top level 1 test 2
    
    running (direct): top
    running (direct): top level 1
    running: top test 1
    running: top test 2
    running: top level 1 test 1
    running: top level 1 test 2
    
    注意钩子的顺序,以及每个钩子在其各自的
    描述
    回调中声明的测试之前执行的方式。

    然后考虑一下这个套件:

    function dump () { console.log("running:", this.test.fullTitle()); }
    function directDump() { console.log("running (direct):", this.fullTitle()); }
    describe("top", function () {
        directDump.call(this);
        it("test 1", dump);
        it("test 2", dump);
        describe("level 1", function () {
            directDump.call(this);
            it("test 1", dump);
            it("test 2", dump);
        });
    });
    
    function dump () { console.log("running:", this.test.fullTitle()); }
    describe("top", function () {
        before(dump);
        it("test 1", dump);
        it("test 2", dump);
        describe("level 1", function () {
            before(function () { throw new Error("foo"); });
            it("test 1", dump);
            it("test 2", dump);
        });
    
        describe("level 1 (second)", function () {
            before(dump);
            it("test 1", dump);
            it("test 2", dump);
        });
    });
    
    使用
    spec
    reporter运行,并仅保持
    运行:
    行,您将获得:

    running: top "before all" hook: dump
    running: top test 1
    running: top test 2
    running: top level 1 "before all" hook: dump
    running: top level 1 test 1
    running: top level 1 test 2
    
    running (direct): top
    running (direct): top level 1
    running: top test 1
    running: top test 2
    running: top level 1 test 1
    running: top level 1 test 2
    
    请注意,
    directDump
    的两个调用是如何在运行其他调用之前运行的。

    后果
  • 如果直接放在调用
    description
    的回调中的任何初始化代码失败,整个运行立即失败。不会执行任何测试。故事结束了

  • 如果在
  • 钩子之前放入
    中的任何初始化代码失败,将包含后果。首先,因为此时需要在
    钩子之前运行一个
    ,所以有机会运行任何提前安排的测试。此外,摩卡只会跳过那些依赖于
    之前的
    钩子的测试。例如,让我们假设这个套件:

    function dump () { console.log("running:", this.test.fullTitle()); }
    function directDump() { console.log("running (direct):", this.fullTitle()); }
    describe("top", function () {
        directDump.call(this);
        it("test 1", dump);
        it("test 2", dump);
        describe("level 1", function () {
            directDump.call(this);
            it("test 1", dump);
            it("test 2", dump);
        });
    });
    
    function dump () { console.log("running:", this.test.fullTitle()); }
    describe("top", function () {
        before(dump);
        it("test 1", dump);
        it("test 2", dump);
        describe("level 1", function () {
            before(function () { throw new Error("foo"); });
            it("test 1", dump);
            it("test 2", dump);
        });
    
        describe("level 1 (second)", function () {
            before(dump);
            it("test 1", dump);
            it("test 2", dump);
        });
    });
    
    如果使用
    spec
    reporter运行它,整个输出(减去堆栈跟踪)将如下所示:

      top
    running: top "before all" hook: dump
    running: top test 1
        ✓ test 1
    running: top test 2
        ✓ test 2
        level 1
          1) "before all" hook
        level 1 (second)
    running: top level 1 (second) "before all" hook: dump
    running: top level 1 (second) test 1
          ✓ test 1
    running: top level 1 (second) test 2
          ✓ test 2
    
    
      4 passing (5ms)
      1 failing
    
      1) top level 1 "before all" hook:
         Error: foo
         [stack trace]
    
    注意a)一些测试是如何在失败的挂钩之前运行的,b)Mocha仍然运行不依赖挂钩的测试


    好吧,Jasmine甚至没有
    before()
    ,这进一步加深了人们对该函数无用的想法。。。