100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Testing

test() and describe() Blocks

How to organize related tests using describe() blocks, and the setup/teardown hooks that run alongside them.

FoundationsBeginner8 min readJul 10, 2026
Analogies

Grouping Tests with describe()

describe('block name', () => { ... }) groups related test() calls under a shared label, which shows up as an indented heading in Jest's output and makes large test suites easier to scan — for example, describe('UserService', () => { test('creates a user', ...); test('rejects duplicate emails', ...); }). Grouping also lets you scope setup/teardown hooks and shared variables to just the tests inside that block, rather than affecting the entire file.

🏏

Cricket analogy: A describe() block is like grouping a bowler's figures by innings on a scorecard — 'Bumrah — 1st Innings' as a labeled section containing each individual delivery's outcome (test), rather than a flat unsorted list of every ball bowled all match.

Setup and Teardown Hooks

Jest provides beforeEach/afterEach to run code before or after every test in the enclosing describe() block (or the whole file if placed outside one), and beforeAll/afterAll to run code once before the first or after the last test in that scope — useful for expensive setup like opening a database connection, versus per-test setup like resetting a mock's call history. A common pattern is beforeEach(() => { jest.clearAllMocks(); }) to ensure mock call counts don't leak between tests, since Jest does not reset mocks automatically unless clearMocks: true is set in configuration.

🏏

Cricket analogy: beforeAll opening a database connection once is like a ground crew preparing the pitch once before a five-day Test match, while beforeEach resetting mocks per test is like the umpires checking the ball's condition before every single over.

javascript
describe('ShoppingCart', () => {
  let cart;

  beforeEach(() => {
    cart = new ShoppingCart();
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  test('starts empty', () => {
    expect(cart.items).toHaveLength(0);
  });

  test('adds an item', () => {
    cart.add({ id: 1, price: 10 });
    expect(cart.items).toHaveLength(1);
  });
});

Hooks declared outside any describe() apply to the whole file. Hooks declared inside a describe() only apply to tests within that block, including nested describe()s — this scoping is what makes hooks composable in large suites.

Nesting describe() Blocks

describe() blocks can be nested to model sub-scenarios, such as describe('ShoppingCart', () => { describe('when empty', () => {...}); describe('with items', () => {...}); }), and Jest runs beforeEach hooks from outer blocks before inner ones, in declaration order — so an outer beforeEach that creates a cart runs before an inner beforeEach that adds items to it. This nesting is purely for organization and shared setup; it doesn't create test isolation between sibling describe blocks beyond what the hooks themselves establish.

🏏

Cricket analogy: Nested describe() blocks are like a scorecard organized by 'Match' containing nested 'Innings' sections, each containing individual 'Over' entries — the outer setup (venue/toss) applies before the inner-specific setup (which bowler is up) takes over.

Sibling describe() blocks do not share state by default, and test order should never be relied upon for correctness — Jest does not guarantee tests run in file order when using certain reporters or --shard/parallel configurations across files. Each test should set up everything it needs via hooks rather than depending on a previous test having run.

test.each and Parameterized Tests

When you need to run the same assertion logic against multiple input/output pairs, test.each([[input1, expected1], [input2, expected2]])('description with %s', (input, expected) => {...}) avoids copy-pasting near-identical test() blocks. The array form uses %s, %d, %i, %p etc. as printf-style placeholders in the description string, while a tagged-template form offers a more readable table layout for larger data sets.

🏏

Cricket analogy: test.each running the same check against multiple input pairs is like a bowling machine testing a batter's technique against a table of deliveries — different lengths, different lines — using one consistent evaluation method instead of writing a separate drill for every single delivery type.

  • describe('name', callback) groups related test() calls and organizes output, and scopes shared hooks/variables.
  • beforeEach/afterEach run around every test in scope; beforeAll/afterAll run once for the whole scope.
  • Jest does not auto-reset mocks between tests unless you call jest.clearAllMocks() or set clearMocks: true.
  • Hooks declared outside any describe() apply file-wide; hooks inside one apply only to that block and its nested blocks.
  • Outer beforeEach hooks run before inner ones, in declaration order, when describe() blocks are nested.
  • Sibling describe()/test() blocks should never depend on execution order or shared mutable state.
  • test.each (array or tagged-template form) runs the same test logic against multiple data rows without duplicating code.

Practice what you learned

Was this page helpful?

Topics covered

#Testing#JestStudyNotes#TestingQA#TestAndDescribeBlocks#Test#Describe#Blocks#Grouping#StudyNotes#SkillVeris