Mocha 如何执行“it”调用?如何同步执行测试?
Posted
技术标签:
【中文标题】Mocha 如何执行“it”调用?如何同步执行测试?【英文标题】:How does Mocha execute the 'it' calls? How to execute tests synchronously? 【发布时间】:2016-08-02 18:48:51 【问题描述】:观察以下测试:
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 中有 Module -> Test -> Asserts。 是在这里吗 描述 -> 描述 -> 是吗?
【问题讨论】:
错误/失败输出是什么? 我将其添加为图片。 看起来回调没有直接执行... 我同意它不是重复的。 @Louis 的根本原因可能相同,但观察到的行为不同。答案也不适用于这个问题。这里发布的答案更适合这个问题。 【参考方案1】:你做错了测试。整个测试、变量设置和所有内容都必须在 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 中的解释器,否则这是不可能的。但是如果您在数组中有一个函数列表并一次执行一个函数,则可以做到这一点。
【讨论】:
我需要一个接一个地做一系列的测试。我可以在一个 it 中做多个期望,但是我怎样才能告诉 mocha 每个期望做什么呢?我正在使用同步事件处理进行一些测试。 每个it
会一个接一个地被同步调用。只需将所有代码移动到 it
块中,它们就会起作用。不建议这样做,因为一个失败的测试将导致所有后续测试失败。【参考方案2】:
回答问题,执行流程是如何工作的。 Mocha 以描述块开头。
在 describe 块中,它首先执行所有不在 it
块中的代码。
因此,在您的代码中,首先执行这 3 条语句,然后再执行 it
块
var i = 0;
i++;
i=7;
最后分配给 i 的值为 7。 现在它将开始执行它的块。
【讨论】:
【参考方案3】:类似 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
当所有三个测试都执行时。
如果真的需要这个序列,你可以使用闭包,但这会增加很多复杂性。
【讨论】:
你确定解决方案是多重的吗?我感觉解决方案可能是多重期望。但我不确定…… 这取决于断言/期望。一般来说,单元测试应该只测试一个“事物”。如果必须使用各种断言/期望来测试这个“一件事”,那么多个断言/期望是有效的/要走的路。如果有不同的单位,拆分它会是更好的选择。尽管如此,如果可能的话,我会尝试在beforeEach
部分设置(环境)测试,以避免混淆
@KeesC.Bakker:it
是一项需要测试的功能。每个特性或功能可能需要断言多个事物。所以这取决于。如果您的多个it
只是测试一个功能,那么将它们组合成一个it
。如果您的单个 it
正在测试两个功能,则将其拆分。关键是将测试读成英文句子:it should do what
,然后添加语法:it('should do what',function())
。如果您可以将it
描述为特性、功能、边缘情况或错误,那么it
应该是一个单独的it
【参考方案4】:
看起来下面是要走的路:
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
映射到 describe
,QUnit.test
映射到 it
,assert
映射到 expect
。
我已经写了一篇关于这个主题的博客:Convert QUnit test to Mocha / Chai。
【讨论】:
也许您应该发布您正在尝试测试的确切内容(例如,如果您想将值从一个测试“携带”到下一个测试,您可以将它们附加到this
对象,它可用于每个测试,或者在 describe
块中声明一个变量,就像 @winner_joiner 在他们的回答中提出的那样)。
我添加了一系列测试。我正在将我的 QUnit 测试移植到 Mocha 框架。
我快速编写了一些代码here。 result
的范围是 describe
块,这意味着您可以在测试之间“重用”它。
您仍然可以为每个期望创建单独的测试(根据 my gist,IMO 比在同一个测试中有很多期望更干净。以上是关于Mocha 如何执行“it”调用?如何同步执行测试?的主要内容,如果未能解决你的问题,请参考以下文章
在 mocha 中,如何在执行另一个测试之前等待异步测试结束?