Dynamically matching files in Jest

Romain Kelifa
Jan 16, 2020 · 5 min read

Article of today is about dynamically matching files for your tests run with Jest.

Use case

Let’s say you have 2 different kinds of tests in your application :

  • unit-tests with files conventionally named like *.spec.js
  • integration tests with files conventionally named like *.test.js which probably require to setup some kind of environment (database, API server, and so on) and tend to run for quite a while

Now let’s imagine you would like to setup your code versioning workflow on GitHub (or another provider) this way :

  • master : main repository branch where you would like to run only Continuous Delivery pipeline
    💡 here all the commits that end up here were previously thoroughly tested in both release and branch CI and you’re confident enough to deploy them automatically
  • release : pre-deploy branch where you would like to run long-lasting integration tests to allow for merging on master, as part of your Continuous Integration pipeline
    💡 here all the unit-tests were previously tested in branch CI so you’re confident enough not to run them again
  • branch : development branch where you would like to run only quick unit-tests to allow for merging on release, as part of your Continuous Integration pipeline
    💡 here you test only the unit-tests to ensure your code abide by its specifications

Concrete examples

There’s probably many more ways to do it but here I will list only 3 of them which IMHO are the easiest ones.

Note : In this example, I used Node.js, Yarn and Typescript.
Typescript adds another requirement : to transpile the *.ts files into *.js files before launching the tests.

I intentionally skipped a few lines in the samples to make the code more readable and focus on Jest configuration (you could apply the same principle to different code bases with different configurations)

Before going into the details, 2 notable facts :

  1. by default, Jest will look for a configuration file named jest.config.js (other formats are accepted too) at the root of your repository
  2. Jest has 2 ways to specify a specific set of files to be run : testMatch (a glob pattern in Jest configuration file) or regexForTestFiles (a regular expression, a.k.a regexp, in the CLI) : you can use either one or the other, but not both at the same time

As you’re about to see, I created npm scripts this way :

  • test : run both unit-tests and integration tests
  • spec : run only unit-tests (*.spec.js)
  • integration : run only integration tests (*.test.js)

The reason why I chose to keep test as the run-it-all script is that by convention yarn test (or npm run test) is the preferred way of running all tests.

Using different configuration files

Some more explanations :

➡️ delete any previously transpiled files (my output folder being dist here) and run tsc command to transpile *.ts files in to *.js files (more on this here)

➡️ npm script hooks to automatically run build script whether we runspec, integration or test scripts : more on this here

➡️ here is the trick : when running test I will run jest using default (jest.config.js), while when running spec or integration I will use different ones by specifying--config argument.
note : --passWithNoTests argument avoid having your tests fail if ever you don't have any test files

Then, setup your configurations :

➡️ actually in this case Jest configuration will only differ by the set of files you want to run, so better reuse the default and just change :

➡️ another configuration file, here you can override testMatch to have Jest run only *.spec.js files :

➡️ another configuration file, here you can override testMatch to have Jest run only *.test.js files :

here is a website to help you write and test your glob

pros and cons

🙂 specify your set of files using glob pattern, which is easier to deal with than regexp

🙁 have to create multiple files for Jest configuration, which you might think of a bit like “files pollution” in your repository

Using regular expressions

➡️ see the previous example for explanations about most of the scripts.
here is the difference :

➡️ set of files to match is provided as regexp :

  • ^(.*\/)*(.*\\.)*(spec)\\.js$ to match only *.spec.js files
  • ^(.*\/)*(.*\\.)*(test)\\.js$ to match only *.test.js files

here is a website to help you write and test your regexp

➡️ only default Jest configuration required :

pros and cons

🙂 no need to create multiple configuration files for Jest configuration

🙁 specify your set of files using regexp pattern, which is more tedious to deal with than glob

Using environment variable

➡️ see the previous examples for explanation about the scripts

➡️ dotenv is a npm library to automatically load environment variables from a .env file, allowing to substitute the pattern in testMatch with an environment variable, for example here JEST_FILES_PATTERN

.env

➡️ here you can specify the pattern you want to use when running your tests

pros and cons

🙂 no need to create multiple configuration files for Jest configuration

🙂 no need to create multiple npm scripts in package.json

🙂 specify your set of files using glob pattern, which is easier to deal with than regexp

🙁 if you forget to specify the environment variable locally or in your CI pipeline, Jest might end up testing an unexpected set of files

And here it is !
As you saw, it’s mostly a matter of preferences.
I hope you enjoyed this article and wish you a great day ✌️

Additionally, as setting up different integration tests environments often requires additional setup, here is a nice article about it using MongoDB.

The Startup

Get smarter at building your thing. Join The Startup’s +724K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store