Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Jest import every test file individually, or does it mount all the references one time before executing?

I have several unit tests, and each module imports a lot of data resources from a JSON file via a method. This IIFE method is imported by every test module, and I'm trying to figure out why my tests are so slow. The JSON data is massive, so I'm guessing that the reason this is the case, is because every test imports the huge data as it is ran. If this is the case, I'll have to modify the method, to return only specific data sets.

So my question is, is the data imported every single time each test module runs, or only once when I execute npm run test?

A basic example of the structure I have: Codesandbox. Say test1.js requires only dataset_1 key from the data json, and the other two test files need dataset_2. Would it be more performant to write a method that returns the required data props to the test file that it is invoked in, or it doesn't matter? Trying my best to phrase this question correctly, please let me know what else I can clarify.

like image 263
Mike K Avatar asked Feb 20 '20 14:02

Mike K


1 Answers

Yup, I think you need to update your tests. This is what the docs say, in the resetModules configuration switch section:

... each test file gets its own independent module registry.

This tallies with the behaviour I've observed. For each test file the whole runtime is rebuilt, meaning all modules are imported from scratch. That makes sense, because it means that common test bugs related to mutable global state not being cleaned up between tests are eradicated.

Also, it's worth noting jest can (if not always does) use subprocesses to run each test, so that it can be parallelized more easily, which is another reason why it makes sense to do a completely fresh setup for each test file. You can switch this off by using --runInBand, but that doesn't change the behaviour, see the example below.

On a default install, you can see the problem by simply putting a console.log() statement in an import file, and then having two tests import it, something like:

mylib.js

console.log('Hello from mylib.js!');

jests/test1.js

const mylib = require('../mylib');
describe('test1', () => {
  it('should be equal', () => {
    expect(1).toEqual(1);
  });
});

jests/test2.js

const mylib = require('../mylib');
describe('test2', () => {
  it('should be equal', () => {
    expect(2).toEqual(2);
  });
});

I get output along the lines of:

 3.2: npm run jest -- --runInBand jests/test*

> [email protected] jest /path/to/cwd
> jest "jests/test1.jest.js" "jests/test2.jest.js"

(node:60746) ExperimentalWarning: The fs.promises API is experimental
 PASS  jests/test1.jest.js
  ● Console

    console.log
      Hello from mylib.js!

      at Object.<anonymous> (mylib.js:1:9)

 PASS  jests/test2.jest.js
  ● Console

    console.log
      Hello from mylib.js!

      at Object.<anonymous> (mylib.js:1:9)


Test Suites: 2 passed, 2 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        1.075 s
Ran all test suites matching /jests\/test1.jest.js|jests\/test2.jest.js/i.
like image 74
daphtdazz Avatar answered Nov 08 '22 15:11

daphtdazz