笑话回顾:什么时候运行?
文章标签
什么时候
tl;dr:执行顺序
- 顶层和describe() 块中的所有内容(其中describe() 块基本上是iife)
- 之前所有()
- 顶级
- 第一级描述()
- 第n级describe()
- 在每个()之前
- 顶级
- 第一级描述()
- 第n级describe()
- 测试()
- 每个之后()
- 第n级describe()
- 第一级描述()
- 顶级
- 毕竟()
- 第n级describe()
- 第一级描述()
- 顶级
免责声明
我假设您对笑话和单元测试有基本的了解。我不会解释钩子的含义。这更多的是备忘单/参考类型的帖子。
有规则
乍一看,笑话似乎有神奇的作用。什么时候执行什么?但如果你想一想,它就会变得明显不那么令人困惑。
也许这些简单的“规则”有帮助:
- 每个文件都是独立执行的:您在 a.test.js 中所做的任何操作都不会影响 b.test.js。 (除非你开始访问外部资源)
- describe() 回调会立即执行。
- 钩子(beforeall/afterall、beforeeach/aftereach)从外部作用域(顶级/模块)到内部作用域(描述)执行。
基本示例
console.log("./<start>");beforeall(() => { console.log("./beforeall");})beforeeach(() => { console.log("./beforeeach");})afterall(() => { console.log("./afterall");})aftereach(() => { console.log("./aftereach");})describe("foo", () => { console.log("./describe(foo)/<start>"); beforeall(() => { console.log("./describe(foo)/beforeall"); }) beforeeach(() => { console.log("./describe(foo)/beforeeach"); }) afterall(() => { console.log("./describe(foo)/afterall"); }) aftereach(() => { console.log("./describe(foo)/aftereach"); }) test("testfoo", () => { console.log("./describe(foo)/test(testfoo)"); }) console.log("./describe(foo)/<end>");})describe("bar", () => { console.log("./describe(bar)/<start>"); beforeall(() => { console.log("./describe(bar)/beforeall"); }) beforeeach(() => { console.log("./describe(bar)/beforeeach"); }) afterall(() => { console.log("./describe(bar)/afterall"); }) aftereach(() => { console.log("./describe(bar)/aftereach"); }) test("testbar", () => { console.log("./describe(bar)/test(testbar)"); }) test("testotherbar", () => { console.log("./describe(bar)/test(testotherbar)"); }) console.log("./describe(bar)/<end>");})console.log("./<end>");</end></end></start></end></start></start>
这是结果(在我删除其他输出后):
./<start>./describe(foo)/<start>./describe(foo)/<end>./describe(bar)/<start>./describe(bar)/<end>./<end>./beforeall./describe(foo)/beforeall./beforeeach./describe(foo)/beforeeach./describe(foo)/test(testfoo)./describe(foo)/aftereach./aftereach./describe(foo)/afterall./describe(bar)/beforeall./beforeeach./describe(bar)/beforeeach./describe(bar)/test(testbar)./describe(bar)/aftereach./aftereach./beforeeach./describe(bar)/beforeeach./describe(bar)/test(testotherbar)./describe(bar)/aftereach./aftereach./describe(bar)/afterall./afterall</end></end></start></end></start></start>
会发生什么?
顶层和描述回调中的所有内容都会立即执行:
./<start>./describe(foo)/<start>./describe(foo)/<end>./describe(bar)/<start>./describe(bar)/<end>./<end>[...]</end></end></start></end></start></start>
顶层的 beforeall 和 afterall 是所有测试的“支撑”。每个只执行一次。
[...]./beforeall[...]./afterall
./describe(*)/beforeall 和 ./describe(*)/afterall 是 that 描述回调中所有测试的大括号。每个只执行一次。
[...]./describe(foo)/beforeall[...]./describe(foo)/afterall./describe(bar)/beforeall[...]./describe(bar)/afterall[...]
beforeeach 和 aftereach 是每个测试周围的大括号。最顶层是外大括号。描述级别是内部大括号。
[...]./beforeeach./describe(*)/beforeeach[...]./describe(*)/aftereach./aftereach[...]
高级版
这是一个带有嵌套描述块的高级示例。它生成 xmlish 结果来强调执行步骤的分层性质。
console.log("<top-level>");beforeall(() => { console.log("<all>");})beforeeach(() => { console.log("<each>");})afterall(() => { console.log("</each></all>");})aftereach(() => { console.log("");})describe("foo", () => { console.log("<describe id='\"foo\"'>"); beforeall(() => { console.log("<all in='\"foo\"'>"); }) beforeeach(() => { console.log("<each in='\"foo\"'>"); }) afterall(() => { console.log("</each></all><!-- in=\"foo\" -->"); }) aftereach(() => { console.log(" <!-- in=\"foo\" -->"); }) test("testfoo", () => { console.log("<test in='\"foo\"' id='\"testfoo\"'></test>"); }) console.log("</describe><!-- id=\"foo\" -->");})describe("bar", () => { describe("barinner", () => { console.log("<describe id='\"barinner\"'>"); beforeall(() => { console.log("<all in='\"barinner\"'>"); }) beforeeach(() => { console.log("<each in='\"barinner\"'>"); }) afterall(() => { console.log("</each></all><!-- in=\"barinner\" -->"); }) aftereach(() => { console.log(" <!-- in=\"barinner\" -->"); }) test("testbarinner", () => { console.log("<test in='\"barinner\"' id='\"testbarinner\"'></test>"); }) console.log("</describe><!-- id=\"barinner\" -->"); }) console.log("<describe id='\"bar\"'>"); beforeall(() => { console.log("<all in='\"bar\"'>"); }) beforeeach(() => { console.log("<each in='\"bar\"'>"); }) afterall(() => { console.log("</each></all><!-- in=\"bar\" -->"); }) aftereach(() => { console.log(" <!-- in=\"bar\" -->"); }) test("testbar", () => { console.log("<test in='\"bar\"' id='\"testbar\"'></test>"); }) test("testotherbar", () => { console.log("<test in='\"bar\"' id='\"testotherbar\"'></test>"); }) console.log("</describe><!-- id=\"bar\" -->");})console.log("</top-level>");
这是经过一些清理和格式化后的输出:
<top-level><describe id="foo"></describe><!-- id="foo" --><describe id="barinner"></describe><!-- id="barinner" --><describe id="bar"></describe><!-- id="bar" --></top-level><all><all in="foo"><each><each in="foo"><test in="foo" id="testFoo"></test></each><!-- in="foo" --></each></all><!-- in="foo" --><all in="bar"><all in="barinner"><each><each in="bar"><each in="barinner"><test in="barinner" id="testBarInner"></test></each><!-- in="barinner" --></each><!-- in="bar" --></each></all><!-- in="barinner" --><each><each in="bar"><test in="bar" id="testBar"></test></each><!-- in="bar" --></each><each><each in="bar"><test in="bar" id="otherBar"></test></each><!-- in="bar" --></each></all><!-- in="bar" --></all>
这就是关于执行顺序的全部知识。