Master Jest test.each: Run a Single Test Template Across Multiple Data Rows
Learn how to use Jest’s test.each to execute the same assertions against many input sets, see each row as an individual test case, and avoid common pitfalls.
23 Sept 2025, 13:31 UTC

Desired Outcome
Run one test template against many argument sets and have Jest report each row as a distinct test case in the CLI output. This gives you fine‑grained pass/fail information and keeps the test suite readable.
Prerequisites
- Node.js 14+ (or the version your project uses).
- Jest installed as a dev dependency:
npm install --save-dev jest - A test file that imports the function you want to test.
- Basic understanding of Jest’s
describe,test, and assertion syntax.
Procedure
- Define the data table. Create an array of arrays where each inner array represents the arguments for one test run.
const cases = [ [1, 2, 3], // a + b = c [0, 0, 0], [-1, 1, 0], [5, 5, 10] ]; - Write the test template. Use
test.eachand interpolate the values into the title and callback.import { add } from './math'; test.each(cases)( 'add(%i, %i) should return %i', (a, b, expected) => { expect(add(a, b)).toBe(expected); } );Placeholders:
%ifor integers,%sfor strings,%ofor objects. Using%son an object will print[object Object], so prefer%oor stringify. - Run the tests. Execute from the project root:
npx jest path/to/add.test.js --verboseJest will list each row as a separate test case.
Expected Checks
- CLI output shows four distinct tests, each with a pass/fail status.
- When a row fails, the error message includes the exact title (e.g.,
add(5, 5) should return 10). - No cross‑row state leakage: resetting any module‑level singletons inside the callback ensures independent runs.
Recovery Options
- Malformed data. Verify that every inner array has the same number of elements as the callback expects.
- Shared mutable state. If the function under test mutates a module‑level object, clone it inside the callback or reset it in a
beforeEachhook. - Grouping related rows. Wrap
test.eachinsidedescribe.eachto group rows under a suite title for better readability.
Limitations & Practical Checks
- Jest’s
test.eachruns synchronously unless you return a promise or useasync/await. For async functions, addasyncto the callback andawaitthe assertion. - ESM support requires Jest 27+ and Node 12+. Verify by running
npx jest --versionand checkingpackage.jsonfortype: "module"if you use .mjs files. - Large data tables can slow the test suite. Consider splitting into multiple
describeblocks or usingdescribe.eachfor logical grouping.
Concrete Example: Testing a Simple Adder
Suppose you have add.js:
export function add(a, b) {
return a + b;
}
And add.test.js uses test.each as shown above. Running npx jest add.test.js --verbose yields:
PASS ./add.test.js
✓ add(1, 2) should return 3 (3 ms)
✓ add(0, 0) should return 0
✓ add(-1, 1) should return 0
✓ add(5, 5) should return 10
Test Suites: 1 passed, 1 total
Tests: 4 passed, 4 total
If you intentionally break one row:
const cases = [
[1, 2, 4], // wrong expected
[0, 0, 0],
[-1, 1, 0],
[5, 5, 10]
];
only the first test will fail, and the output will pinpoint that specific row.
Conclusion
Using test.each keeps your test code DRY, provides clear per‑row diagnostics, and scales well for simple data‑driven scenarios. Just remember to avoid mutating shared state and to choose the right placeholder for interpolated values.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.