Mocha的before()函数的目的是什么?

Mad*_*iha 16 javascript unit-testing mocha.js

Mocha有几个"钩子"可以在与测试用例本身分开的测试中运行辅助功能(清除数据库,创建模拟文件等).

但是,在before()(不是 beforeEach()我得到的那个)的情况下,它似乎非常多余.

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

以下两者之间没有可观察到的差异:

describe('Something', function() {
    before(doSomePreTestLogic);
    //Tests ahoy
});
Run Code Online (Sandbox Code Playgroud)

describe('Something', function() {
    doSomePreTestLogic();
    //Tests ahoy
});
Run Code Online (Sandbox Code Playgroud)

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

jma*_*777 12

您可能会before()在测试中选择挂钩,这有几个不同的原因:

语义

这可能是最大的一个.有时您可能需要在运行实际测试之前执行任务,例如在数据库中填充一些虚拟数据.您当然可以在测试本身中执行此操作,但如果您在预填充时遇到错误,并且在运行实际测试用例之前,则会抛弃您的报告.通过有一个before()钩子,你有一个逻辑的,语义上有效的位置来插入这种逻辑.

清除异步测试

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

与其他钩子的一致性:

摩卡还提供了其他几个挂钩,即:after(),beforeEach(),和afterEach().你可能也会问同样的问题关于所有这些其他钩子,但是如果你认为它们中的任何一个都有一个经过验证的存在,那么before()真的需要包含它来完善API.


Lou*_*uis 5

结果

直接放在describe建立测试套件的回调代码中。我在谈论的是对it函数的调用,但这些函数可能会遍历表或文件以声明一堆测试(通过it在循环中进行调用)。

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

所有其他考虑都是次要的。

让我解释...

背景

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

  1. 它发现存在哪些测试。在这个阶段,会立即执行传递给回调describe和记录以后调用传递给申报测试(功能回调it等)和函数声明挂钩(beforebeforeEachafter等)。

  2. 它运行测试。在此阶段,它将运行先前记录的回调。

区别

因此,请考虑以下示例:

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);
    });
});
Run Code Online (Sandbox Code Playgroud)

请注意,它fullTitle给出了测试的全名,从顶层开始describe,经过嵌套describeit包含调用的或挂钩的任何嵌套。与spec记者一起运行,仅保留running:台词,您将获得:

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
Run Code Online (Sandbox Code Playgroud)

注意钩子的顺序,以及每个钩子如何在各自describe回调中声明的测试之前立即执行。

然后考虑这个套件:

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);
    });
});
Run Code Online (Sandbox Code Playgroud)

spec记者一起运行,仅保留running:台词,您将获得:

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
Run Code Online (Sandbox Code Playgroud)

请注意,这两个调用如何directDump运行的。

后果

  1. 如果直接放在回调中的任何初始化代码describe失败,则整个运行会立即失败。不会执行任何测试。故事结局。

  2. 如果放入before挂钩中的任何初始化代码失败,则将包含后果。一方面,由于before仅在当前需要运行钩子,因此有机会运行任何较早计划的测试。同样,Mocha将仅跳过那些依赖于before挂钩的测试。例如,让我们假设这个套件:

    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);
        });
    });
    
    Run Code Online (Sandbox Code Playgroud)

    如果使用spec报告程序运行它,则整个输出(减去堆栈跟踪)将类似于:

      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]
    
    Run Code Online (Sandbox Code Playgroud)

    请注意a)失败的挂钩之前如何运行某些测试,以及b)Mocha仍然运行不依赖挂钩的测试。