Mocha 如何执行 'it' 调用?如何同步执行测试?

How does Mocha execute the 'it' calls? How to execute tests synchronously?

观察以下测试:

describe("Testing i", function(){

    var i = 0;
    it('i should be 0', function() {
        expect(i).to.equal(0);
    });

    i++;
    it('i should be 1', function() {
        expect(i).to.equal(1);
    });

    i= 7;
    it('i should be 7', function() {
        expect(i).to.equal(7);
    });
});

前两个测试失败。但我不知道为什么!我做错了什么?

测试显示如下:

我正在将 QUnit 移植到 Mocha,我正在寻找断言的位置。
在 QUnit 中,您有模块 -> 测试 -> 断言。
是这里吗 描述 -> 描述 -> 是?

类似 Mocha 文档的解决方案 https://mochajs.org/

describe("Testing i", function(){

    var i;
    it('i should be 0', function() {
        i = 0;
        expect(i).to.equal(0);
    });


    it('i should be 1', function() {
        i++;
        expect(i).to.equal(1);
    });

    it('i should be 7', function() {
        i= 7;
        expect(i).to.equal(7);
    });
});

调用顺序,如问题中所问
我使用本文 http://cwinters.com/2014/09/26/mocha-nested-hook-ordering.html

中的改编代码对其进行了测试

这是代码,我用

'use strict';

describe('level 1', function() {
  before(function() { console.log("L1 - before") });
  beforeEach(function() { console.log("L1 - beforeEach") });
  after(function() { console.log("L1 - after") });
  afterEach(function() { console.log("L1 - afterEach") });

console.log("inner DESCRIBE BEFORE L1A")  // equivalent to asigning the variable the first time
  it('L1 test A', function() {});
 console.log("inner DESCRIBE BEFORE L1B") // equivalent to asigning the variable the second time
  it('L1 test B', function() {});

  describe('level 2', function() {
    before(function() { console.log("L2 - before") });
    beforeEach(function() { console.log("L2 - beforeEach") });
    after(function() { console.log("L2 - after") });
    afterEach(function() { console.log("L2 - afterEach") });

    it('L2 test A', function() {});
    it('L2 test B', function() {});
  });
});

这里是结果

inner DESCRIBE BEFORE L1A     // execute First
inner DESCRIBE BEFORE L1B     // execute Second


  level 1                     // now the test are executed
L1 - before
L1 - beforeEach
    √ L1 test A
L1 - afterEach
L1 - beforeEach
    √ L1 test B
L1 - afterEach
    level 2
L2 - before
L1 - beforeEach
L2 - beforeEach
      √ L2 test A
L2 - afterEach
L1 - afterEach
L1 - beforeEach
L2 - beforeEach
      √ L2 test B
L2 - afterEach
L1 - afterEach
L2 - after
L1 - after


4 passing (64ms)

=> describe 块将立即执行,因此在调用任何其他函数之前,对同一变量的多个变量赋值将被最后一个覆盖。 前两个测试失败,因为 i==7 当所有三个测试都执行时。

如果确实需要序列,您可以使用闭包,但这会增加很多复杂性

你做错了测试。整个测试、变量设置等都必须在 it 函数中。

it 函数所做的只是将您的测试推送到一个列表,该列表将由 describe 函数或 mocha 本身执行。 it 函数不执行测试。

编写测试的正确方法如下:

describe("Testing i", function(){

    it('i should be 0', function() {
        var i = 0;
        expect(i).to.equal(0);
    });

    it('i should be 1', function() {
        var i = 0;
        i++;
        expect(i).to.equal(1);
    });

    it('i should be 7', function() {
        var i = 0;
        i = 7;
        expect(i).to.equal(7);
    });
});

FWIW。除非您将参数传递给 it 函数的回调,否则所有测试都会同步执行。只是它们没有在 describe 函数内部执行。 it 函数只是将所有 it 调用编译成测试列表。

因此,如果您需要进行一系列操作,您可以这样做:

describe("Testing i", function(){
    var i;

    it('i should be 0', function() {
        i = 0;
        expect(i).to.equal(0);
    });

    it('i should be 1', function() {
        i++;
        expect(i).to.equal(1);
    });

    it('i should be 7', function() {
        i = 7;
        expect(i).to.equal(7);
    });
});

但是请注意,不推荐这样做,因为如果第一个测试失败,那么接下来的一些测试也可能会失败。在此示例中,如果第一个测试因 i 的值不为 0 而失败,则第二个测试也将失败。但是,这种模式对于需要很长时间执行的步骤可能很有用(例如网站登录)。


为什么要这样做?

这允许 mocha 做像进度条等花哨的测试报告。不知道有多少测试 运行(测试是一个 it 函数),mocha 无法知道有多少百分比绘制进度条。

它还允许 mocha 对错误消息进行精美的格式化。如果您使用过 mocha,您会注意到 mocha 会收集所有错误消息(失败)并在最后打印出来。为此,mocha 所做的是以受控方式一次执行一个测试(it 函数)并收集抛出的任何错误。如果你只依赖 javascript 语法,那是不可能的,除非你破解 C 中的解释器。但是如果你在数组中有一个函数列表并一次执行一个函数,你就可以做到这一点。

看起来下面是要走的路:

describe("Testing i", function(){

    it('i increments', function(){

        var i = 0;
        expect(i, 'i should be 0').to.equal(0);

        i++;
        expect(i, 'i should be 1').to.equal(1);

        i = 7;
        expect(i, 'i should be 7').to.equal(7);
    });

});

QUnit.module 映射到 describeQUnit.test 映射到 itassert 映射到 expect

我写了一篇关于这个主题的博客:Convert QUnit test to Mocha / Chai

回答问题,执行流程是如何工作的。 Mocha 以 describe 块开头。

首先在 describe 块中执行所有不在 it 块中的代码。

因此在您的代码中,首先执行这 3 个语句,然后再执行 it 个块

var i = 0;
  i++;
  i=7;

最后分配给 i 的值是 7。 现在它将开始执行块。