Skip to content

Jest

vibrant jester figure in dramatic lighting

Reduce unit tests boilerplate with Jest’s .each syntax

When writing unit tests, especially in JavaScript/TypeScript with Jest, you often run into a common problem: repetition.
Imagine testing a function with several input-output pairs. The tests can become bloated and harder to read.
This is where Jest’s .each syntax shines. It lets you write cleaner, data-driven tests with minimal duplication.

The Problem: Repetitive Test Cases

Take a simple sum function:

function sum(a, b) {
  return a + b;
}

Without .each, you might write your tests like this:

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

test('adds 2 + 3 to equal 5', () => {
  expect(sum(2, 3)).toBe(5);
});

test('adds -1 + -1 to equal -2', () => {
  expect(sum(-1, -1)).toBe(-2);
});

These tests work, but they are verbose. You repeat the same logic over and over with only the inputs and expected results changing.

The Solution: Jest’s .each Syntax

Jest’s .each allows you to define test cases as data and reuse the same test body.
Here is the same example using .each:

describe('sum', () => {
  test.each([
    [1, 2, 3],
    [2, 3, 5],
    [-1, -1, -2],
  ])('returns %i when %i + %i', (a, b, expected) => {
    expect(sum(a, b)).toBe(expected);
  });
});

This single block of code replaces three separate test cases.
Each array in the .each list corresponds to a test run, and Jest automatically substitutes the values.

Bonus: Named Arguments with Tagged Template Literals

You can also use named arguments for clarity:

test.each`
  a    | b    | expected
  ${1} | ${2} | ${3}
  ${2} | ${3} | ${5}
  ${-1}| ${-1}| ${-2}
`('returns $expected when $a + $b', ({ a, b, expected }) => {
  expect(sum(a, b)).toBe(expected);
});

This syntax is more readable, especially when dealing with longer or more descriptive variable names.
It reads like a mini table of test cases.

Why Use .each?

  • Less boilerplate: Define the test once and reuse it.
  • Better readability: Data-driven tests are easier to scan.
  • Easier maintenance: Add or remove cases without duplicating test logic.
  • Fewer mistakes: Repeating the same code invites copy-paste errors.

Use Case: Validating Multiple Inputs

Suppose you are testing a validation function like isEmail. You can define all test cases in one place:

test.each([
  ['user@example.com', true],
  ['not-an-email', false],
  ['hello@world.io', true],
  ['@missing.local', false],
])('validates %s as %s', (input, expected) => {
  expect(isEmail(input)).toBe(expected);
});

This approach scales better than writing individual test blocks for every email address.

Conclusion

Jest’s .each is a powerful way to reduce duplication in your test suite.
It helps you write cleaner, more maintainable, and more expressive tests.
Next time you find yourself writing nearly identical test cases, reach for .each—your future self will thank you.