提问人:Madara's Ghost 提问时间:10/11/2014 最后编辑:Madara's Ghost 更新时间:7/8/2017 访问量:3850
Mocha 的 before() 函数的目的是什么?
What is the purpose of Mocha's before() function?
问:
Mocha 有几个“钩子”,用于在独立于测试用例本身的测试中运行辅助功能(清除数据库、创建模拟文件等)。
但是,在(不是,我得到的那个)的情况下,它似乎很多余。before()
beforeEach()
before()
在当前套件中的所有测试之前运行一次逻辑,那么为什么我甚至需要将其包装在一个函数中呢?
以下两者之间没有明显的区别:
describe('Something', function() {
before(doSomePreTestLogic);
//Tests ahoy
});
和
describe('Something', function() {
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()
与其他钩子的一致性:
Mocha 还提供了其他几个钩子,即:、 和 。你可能也可以对所有其他钩子提出同样的问题,但如果你相信它们中的任何一个都具有经过验证的存在,那么真的需要包括在内来完善 API。after()
beforeEach()
afterEach()
before()
结果
直接放入将构建测试套件的回调代码中。我说的是调用,但也包括可以循环表或文件以声明一堆测试的函数(通过在循环中调用)。describe
it
it
将实际初始化测试所依赖状态的代码放在钩子中。
所有其他考虑因素都是次要的。
让我解释一下......
背景
Mocha 分两个阶段执行测试套件:
它发现存在哪些测试。在此阶段,它将立即执行传递给并记录传递给声明测试的函数(等)和声明钩子的函数(、、等)的回调以供将来调用。
describe
it
before
beforeEach
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);
});
});
请注意,它给出了从顶层开始的测试的全名,通过任何嵌套到包含调用的 or 钩子。与记者一起运行并仅保留行,您将得到:fullTitle
describe
describe
it
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
请注意钩子的顺序,以及每个钩子在其各自的 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);
});
});
与记者一起运行并仅保留行,您将得到: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
请注意,对 directDump
的两次调用都是在运行其他任何操作之前运行的。
后果
如果直接放入回调中的任何初始化代码失败,则整个运行将立即失败。不会执行任何测试。故事到此结束。
describe
如果放在钩子中的任何初始化代码失败,则包含后果。首先,由于钩子在需要的那一刻运行,因此之前安排的任何测试都有机会运行。此外,Mocha 只会跳过那些依赖于钩子的测试。例如,假设这个套件:
before
before
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); }); });
如果使用报告器运行它,则整个输出(减去堆栈跟踪)将如下所示:
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]
请注意 a) 某些测试在失败的钩子之前运行,b) Mocha 仍然运行不依赖于钩子的测试。
评论
before()