Reduce unit tests boilerplate with Jest’s .each syntax

Marios Fakiolas
ITNEXT
Published in
4 min readAug 9, 2018

--

Unit tests are crucial in web development in order to end-up with maintainable and well structured codebase. As you get, this post will not try to persuade you about tests importance. This is taken for granted.

Unfortunately there is a problem and the problem we face while writing unit tests is that we have to repeat ourselves a lot in order to add all these assertions with describe / it format. Yeap, it is true. Writing tests takes time.

So what we do? We have to find ways to automate the whole process as much as possible in order to write tests faster. For those that might wonder, writing less tests is not an option.

.each for the win

There is a pretty cool feature named .each that was included in Jest 23. This library got inspired by mocha-each. It started as a third party package named jest-each before becoming available by Jest itself in version 23. If you still use an older version of Jest you can install jest-each package separately.

How it works?

Because of .each we can write tens of assertions in a couple of lines so that we can avoid repeating ourselves. The only thing we have to do is to declare our variables in a dynamic fashion and then make the assertion just once by using these variables. These are used even in the assertion’s description.

Sounds fun? Let’s dive into code then. We have the following pure function and we want to unit-test it:

function add(x, y) {
return x + y;
}

We can select random pairs of numbers and provide some assertions in order to verify that we get always the expected result:

describe('test add method', () => {
it ('should return 5 when 2 and 3 are used', () => {
expect(add(2, 3)).toEqual(5);
});
it ('should return 50 when 20 and 30 are used', () => {
expect(add(20, 30)).toEqual(50);
});
it ('should return -5 when -2 and -3 are used', () => {
expect(add(-2, -3)).toEqual(-5);
});
});

Awesome. We wrote our assertions but it is obvious that we had to repeat ourselves a little per it statement right? If we take a closer look we ‘ll notice that the only changes per assertion are the new parameters and the expected result.

How can we tackle this? It would be nice if we could declare only the parameters and the expected result in one place and then call the assertion for each one of these combos in a dynamic fashion.

Let’s refactor our tests by using it.each :

describe('test add method', () => {
it.each`
a | b | result
${2} | ${3} | ${5}
${20} | ${30} | ${50}
${-2} | ${-3} | ${-5}
`('should return $result when $a and $b are used', ({a, b, result}) => {
expect(add(a, b)).toEqual(result);
});
});

Nice!! Far less boilerplate and so readable right? We can check the expected results in an eye blink.

This will return the following result in console:

How can i use it in a ReactJS component?

Let’s say we have the following Button component:

import React from 'react';
import cn from 'classnames';
import PropTypes from 'prop-types';
const Button = ({ isPrimary, isDanger, isSuccess }) => (
<button
className={cn('button', {
'is-primary': isPrimary,
'is-danger': isDanger,
'is-success': isSuccess,
})}
/>
);
Button.propTypes = {
isPrimary: PropTypes.bool,
isDanger: PropTypes.bool,
isSuccess: PropTypes.bool,
};
Button.defaultProps = {
isPrimary: false,
isDanger: false,
isSuccess: false,
};
export default Button;

We can easily use Jest, enzyme and .each pattern to unit-test all these classes:

import React from 'react';
import { shallow } from 'enzyme';
import Button from './Button';
let props;beforeEach(() => {
props = {
isPrimary: false,
isDanger: false,
isSuccess: false,
};
});
describe('test Button component', () => {
it.each`
propName | propValue | className | result
${'isPrimary'} | ${true} | ${'is-primary'} | ${true}
${'isDanger'} | ${true} | ${'is-danger'} | ${true}
${'isSuccess'} | ${true} | ${'is-success'} | ${true}
`('should have class $className when prop $propName is equal to $propValue', ({propName, propValue, className, result}) => {
props = { ...props, [propName]: propValue };
const enzymeWrapper = shallow(<Button {...props} />);
expect(enzymeWrapper.hasClass(className)).toEqual(result);
});
});

I am pretty sure you get how fast and scalable this is. Let’s add some extra assertions in there to prove this:

it.each`
propName | propValue | className | result
${'isPrimary'} | ${false} | ${'is-primary'} | ${false}
${'isDanger'} | ${false} | ${'is-danger'} | ${false}
${'isSuccess'} | ${false} | ${'is-success'} | ${false}
`('should have not class $className when prop $propName is equal to $propValue', ({propName, propValue, className, result}) => {
props = { ...props, [propName]: propValue };
const enzymeWrapper = shallow(<Button {...props} />);
expect(enzymeWrapper.hasClass(className)).toEqual(result);
});

To be honest these tests are not that useful in real life since they are checking that classnames package is doing its job which is kind of over-engineering 😃

Conclusion

I am pretty confident that now you know how you can take advantage of .each and reduce all this boring boilerplate code you have to repeat again and again in your unit tests. Cheers!!

--

--

I help people solve real-life problems through web technologies 🚀 — Founder, Leader, and Entrepreneur at helloworld.gr