TL;DR: Execution Order
- Everything on the top-level and in
describe()
blocks (wheredescribe()
blocks are basically IIFEs) -
beforeAll()
- top-level
- 1st level
describe()
- Nth level
describe()
-
beforeEach()
- top-level
- 1st level
describe()
- Nth level
describe()
test()
-
afterEach()
- Nth level
describe()
- 1st level
describe()
- top-level
- Nth level
-
afterAll()
- Nth level
describe()
- 1st level
describe()
- top-level
- Nth level
Disclaimer
I assume you have a basic understanding of jest and unit-testing. I will not explain the meaning of the hooks. This is more of cheat-sheet/reference type of post.
There are Rules
At first jest seems to do stuff magically. What gets executed when? But if you think about it for a minute it gets obvious less confusing.
Maybe these simple "rules" help:
- Each file is executed independently: nothing you do in
A.test.js
affectsB.test.js
. (unless you start to access external resources) -
describe()
callbacks are executed immediately. - hooks (
beforeAll
/afterAll
,beforeEach
/afterEach
) are executed from outer scope (top-level/module) to inner scope (describe).
Basic Example
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>");
This is the result (after I removed other output):
./<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
What happens?
Everything on the top-level and in describe callbacks is executed immediately:
./<start>
./describe(foo)/<start>
./describe(foo)/<end>
./describe(bar)/<start>
./describe(bar)/<end>
./<end>
[...]
beforeAll
and afterAll
on the top-level are a "brace" around all tests. Each executed only once.
[...]
./beforeAll
[...]
./afterAll
./describe(*)/beforeAll
and ./describe(*)/afterAll
are a brace around all tests in that describe
callback. Each executed only once.
[...]
./describe(foo)/beforeAll
[...]
./describe(foo)/afterAll
./describe(bar)/beforeAll
[...]
./describe(bar)/afterAll
[...]
beforeEach
and afterEach
are a braces around each test
. The top-level is the outer brace. The describe
level is the inner brace.
[...]
./beforeEach
./describe(*)/beforeEach
[...]
./describe(*)/afterEach
./afterEach
[...]
Advanced Version
This is an advanced example with a nested describe block. It produces XMLish results to emphasize the hierarchical nature of the execution steps.
console.log("<top-level>");
beforeAll(() => {
console.log("<all>");
})
beforeEach(() => {
console.log("<each>");
})
afterAll(() => {
console.log("</all>");
})
afterEach(() => {
console.log("</each>");
})
describe("foo", () => {
console.log("<describe id=\"foo\">");
beforeAll(() => {
console.log("<all in=\"foo\">");
})
beforeEach(() => {
console.log("<each in=\"foo\">");
})
afterAll(() => {
console.log("</all> <!-- in=\"foo\" -->");
})
afterEach(() => {
console.log("</each> <!-- in=\"foo\" -->");
})
test("testFoo", () => {
console.log("<test in=\"foo\" id=\"testFoo\" />");
})
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("</all> <!-- in=\"barinner\" -->");
})
afterEach(() => {
console.log("</each> <!-- in=\"barinner\" -->");
})
test("testBarInner", () => {
console.log("<test in=\"barinner\" id=\"testBarInner\" />");
})
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("</all> <!-- in=\"bar\" -->");
})
afterEach(() => {
console.log("</each> <!-- in=\"bar\" -->");
})
test("testBar", () => {
console.log("<test in=\"bar\" id=\"testBar\" />");
})
test("testOtherBar", () => {
console.log("<test in=\"bar\" id=\"testOtherBar\" />");
})
console.log("</describe> <!-- id=\"bar\" -->");
})
console.log("</top-level>");
This is the output after some cleanup and formatting:
<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" />
</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" />
</each> <!-- in="barinner" -->
</each> <!-- in="bar" -->
</each>
</all> <!-- in="barinner" -->
<each>
<each in="bar">
<test in="bar" id="testBar" />
</each> <!-- in="bar" -->
</each>
<each>
<each in="bar">
<test in="bar" id="otherBar" />
</each> <!-- in="bar" -->
</each>
</all> <!-- in="bar" -->
</all>
That's all there is to know about the execution order.
Top comments (0)