DEV Community

Robert Marshall
Robert Marshall

Posted on • Originally published at robertmarshall.dev on

How to Loop over Jest Unit Tests


This article was originally posted (and is more up to date) at https://robertmarshall.dev/blog/how-to-loop-in-jest-unit-tests/


Sometimes when writing Jest unit tests you are going to want to be able to loop over items to quickly test different cases. Whether this be looping over an array of items, or counting between numbers in your Jest Test. This will massively simplify your Jest test suite.

There are a number of ways to do this. This post aims to outline the ways that I have looped through Jest tests in the past.

Looping over tests with Jest.Each

For very basic repetitive Jest tests I would use jest.each. It allows you to keep duplicating the same test with different data. You can write the test once and let the data do the work.

Using Basic Arrays and printf

An example of this is:

test.each([
  [1, 1, 2],
  [1, 2, 3],
  [2, 1, 3],
])('.add(%i, %i)', (a, b, expected) => {
  expect(a + b).toBe(expected);
});
Enter fullscreen mode Exit fullscreen mode

The above code is taking in a set of data within an array, The name of the test using printf to inject parameters into the text, and the arguments to be passed into the test itself.

For more information about jest.each take a look at the Jest documentation.

Using Array of Objects

Rather than using printf, you can pass in an array of objects and reference them using string literals. Like so:

test.each([
  {a: 1, b: 1, expected: 2},
  {a: 1, b: 2, expected: 3},
  {a: 2, b: 1, expected: 3},
])('.add($a, $b)', ({a, b, expected}) => {
  expect(a + b).toBe(expected);
});
Enter fullscreen mode Exit fullscreen mode

I personally prefer this. It is more explicit in what each item is, and allows you to build a more complex test data set.

Using Jest.Each with a Table

The jest.each API also lets you pass data into it in a more β€˜visual’ way. Using one large string literal you can shape the data in a table.

This looks like:

test.each`
  a | b | expected
  ${1} | ${1} | ${2}
  ${1} | ${2} | ${3}
  ${2} | ${1} | ${3}
`('returns $expected when $a is added $b', ({a, b, expected}) => {
  expect(a + b).toBe(expected);
});
Enter fullscreen mode Exit fullscreen mode

The first row sets up the table headings, and the rest of the rows using template literals to add the values. Then the test title itself using template literals to inject the data into the string.

Not my top choice, but some people like this way of handling the tests.

Using a For Loop in Jest Tests

The for loop is my go to when wanting to dynamically loop through Jest tests. In this way of writing loops in jest there is no need for the printf variable injection. Call me old fashioned (or wrong), but I also like the flexibility of being able to fully control the tests, and how they are created.

For example, the for loop approach allows me to loop describe jest test blocks, as well as the unit tests inside. However with this freedom comes the need to restrict yourself. Otherwise the tests could become to over-engineered and end up being too confusing.

Simple tests are better.

const testData = [
    { a: 1, b: 1, expected: 2 },
    { a: 1, b: 2, expected: 3 },
    { a: 2, b: 1, expected: 3 }
];

for (let i = 0; i < testData.length; i += 1) { it(`.add(${testData[i].a}, ${testData[i].b})`, () => {
        expect(testData[i].a + testData[i].b).toBe(testData[i].expected);
    });
}
Enter fullscreen mode Exit fullscreen mode

The above shows how the for loop would be used to create dynamically generated Jest tests. However it should be used sparingly, and the jest.each will be able to handle most situations. The for loop is really more for complex situations.

For more Jest hints and tips take a look at the Jest Testing Category!

Hopefully this helped you, and if you have any questions you can reach me at: @robertmars

Top comments (0)