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);
});
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);
});
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);
});
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);
});
}
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)