Separating unit and integration tests in Jest

Alberto Gualis
Coding Stones
Published in
4 min readJun 1, 2018

Update (October 2019)

Before reading this post, you should check this package by Eugene Manuilov which is probably the simplest solution for most cases. As he said in the comments:

As of today there is “jest-runner-groups” package that allows you tag your test files and execute groups of tests with Jest. No need to mess with configs anymore. Just add a docblock to your test file with “@group” parameter and then use “ — group=yourgroup” in the command line.

When you test your frontend application, it is usual to use doubles to test the communication with external services like, for example, the backend.

For instance, when we test a component loading a list of objects from the backend, we don’t make real http requests because we want the test to be fast and reliable. However, we will also need some special tests that perform real requests to the backend to check that our doubles are correct, in other words, tests checking that our contract is not broken. That’s why many people call them contract tests.

I don’t want to start another discussion about types of tests so I will just say that sometimes, depending on our context (teams arrangement, branching strategy, infrastructure…), it is convenient to differentiate between fast/independent tests and slow/external_system_dependent tests. I will call them unit and integration tests, but you can call them how you prefer, the important thing is being able to run them separately.

It’s great to have a complete suite that tests both internal and external pieces, but sometimes we’d like to run them separately

TLDR

You can have several jest configuration files with different testRegex setup to differentiate between your test suites:

npm scripts in my package.json

How I came up with this solution?

There are some test runners that allow us to easily separate our suites. For example, in Rspec you can tag your tests and just run the ones having a concrete tag. I was looking for that option in jest but I just found this feature request (not being considered by now) Is there any other solution? Of course it is:

We can use the testRegex option in jest configuration to only run the tests matching a regular expression.

For instance, if we just want to run the tests ending with .spec.js we can use the regex \.spec\.js$ in our config file, but we have to be very careful because we define our setup in a JS object like this:

// package.json...
jest: {
...

"testRegex": "PUT_YOUR_REGEX_HERE",
...
}
...

and jest will parse this JS object as a string so we will need to escape the backslashes inside our regex. Therefore, our config file will be like this:

// package.json...
jest: {
...

config.testRegex = "\\.spec\\.js$"
...
}
...

But, how do we run tests matching a different regex? Let’s see an example:

I want to have a special filename to differentiate the integration tests. I will use custom sufix .ispec.js so I create integration tests like:

my-fancy-integration-test.ispec.js

But those files will not be run by the default setup because they don’t match our default regex. What can we do? We can just use the — testPathPattern option when we run jest:

jest --testPathPattern=ispec\\.js$

And we can setup different scripts in our package.json like this:

//Package.json...
"scripts": {
...
"unit": "jest",
"integration": "jest --testPathPattern=ispec\\.js$"
,
...
}
...

And we are done! 🎉🎉 But wait! What if I want to have a different context when I run the different suites. Can we improve the previous configuration?

Using different files for each test type

One of the most important rules in software development is having different pieces with clear responsibilities. That’s why I don’t like to define the jest setup options inside my package.json. I prefer to extract them into a separate file (by default jest.config.js).

But what if we want to have different options for different suites? We can create different files and use -c option to choose the needed one:

jest scripts inside package.json

And we can just reuse the default options and override just what we need:

// jest.config.integration.jsvar config = require('./jest.config')
config.testRegex = "ispec\\.js$" //Overriding testRegex option
console.log('RUNNING INTEGRATION TESTS')
module.exports = config

Are you using a different/simpler approach? Please tell us so we can improve!

Happy testing! ✅✅✅

--

--