Jest: Slow React Tests

Created on 8 Aug 2014  ·  80Comments  ·  Source: facebook/jest

Thanks for React and Jest. Loving the combo. Anyhow, I am used to running tests in _livereload_ mode. So anytime a test file is saved, my tests are automatically run. I got this working correctly, but my tests are taking almost 3 seconds to run. That is just with one test file. I am running the files through the preprocessor, so I suspect that is where the problem lies. Do you have any suggestions on how to get the tests to run quickly or any advice on how to speed up the TDD / BDD workflow?

Enhancement

Most helpful comment

My tests are at 14 seconds long, even after using all of the optimizations recommended this far. Even with 16GB RAM and SSD. Jest is totally unusable in its current state. Sorry, switching to Karma.

All 80 comments

Hi Tyron. Had this issue with 20+ seconds for one file :)
The thing was that I've configured to just run 'jest' in the root directory. And there're LOTS of subdirs that Jest was checking for tests. Specifying a path for tests reduced this time more than 10 times now. And I've got a coffee preprocessor too. In package.json
"scripts": {
....
"test": "jest path/to/modules/to/test"
}

BTW, are you preprocessing coffee or what? :)

Thanks for getting back to me @gothy. I am using regular JS with JSX. I am just running my tests through the JSX preprocessor like the example (https://github.com/facebook/jest/tree/master/examples/react). The example is also taking about 2.5 - 3 seconds to run. The jQuery example takes less than a second. Is the JSX preprocessor meant to take so much time when processing your JSX files?

React Test

screen shot 2014-08-08 at 1 46 05 pm

jQuery Test

screen shot 2014-08-08 at 1 54 55 pm

Ah, I didn't use it for JSX. Can't say anything on this processor. Maybe it's actually slow. I've found my issue with directories on a real project with loads of old stuff :)

I experienced a similar issue with Coffeescript preprocessor. I think the problem here is that the preprocessor tries to process your dependencies as well. If you happen to require lots of things, it slows down.

I definitely also experience slow tests with jest :(

I'm experiencing the same thing. I don't think it has to do with the preprocessing (JSX processing on this small file is fast). I commented out all of the code in the example test except one of the following require statements and the test still takes 4 seconds. As soon as I comment them out, the test takes 0.1s. I did a little digging and it looks like the HasteModuleLoader is having to process 490 required packages (_shouldMock()) and not mock them when you require the react/addons.

var React = require('react/addons');

or

var CheckboxWithLabel = require('../CheckboxWithLabel.js');

I removed the following var React = require('react/addons'); and still ran the files through the preprocessor. I got maybe 0.2 second improvement. If I removed the preprocessor, I get the following results:

With the JSX preprocessor
screen shot 2014-08-10 at 5 35 22 pm

Without the JSX preprocessor
screen shot 2014-08-10 at 5 34 12 pm

I prefer Mocha over Jasmine and decided to setup a gulpfile that would build the react component then run it through the mocha test suite (snippet below).

function buildScript(file, watch) {
  var bundler = browserify(file);
  var stream;
  bundler.transform(reactify);
  stream = bundler.bundle();
  return stream.on('error', handleErrors)
  .pipe(source(file))
  .pipe(gulp.dest(buildDir + '/'))
  .pipe(mocha({ reporter: 'list' }));
}

It still has to preprocess the JSX file using reactify, but rids the warning message for slow tests. So the runtime still takes just under 2 seconds, but the actual test is about 32ms. Still deciding if using JSX is worth it.

Oh you're right. I tested the jest react example not using JSX and it went from close to 4 seconds down to 0.75 seconds. Makes me really think if it's worth it to use JSX. On a big project, it's going to get slow pretty quickly unless I have a lot of different packages. I wonder if the preprocessor is run on all 490 requires and not just that single file. There is no way it should take 3 seconds for that simple component.

Either way, I really really need my tests to be fast for my workflow. I still need to figure out how to at least run a single suite. In jasmine I could use "ddescribe" or "iit" instead of "describe" and "it" to run a single test or suite. Jest is SO nice, I just need a fast workflow now.

var React = require('react');

var CheckboxWithLabel = React.createClass({displayName: 'CheckboxWithLabel',
    getInitialState: function() {
        return { isChecked: false };
    },
    onChange: function() {
        this.setState({isChecked: !this.state.isChecked});
    },
    render: function() {
        return (
            React.DOM.label(null,
                React.DOM.input(
                    {type:"checkbox",
                        checked:this.state.isChecked,
                        onChange:this.onChange}
                ),
                this.state.isChecked ? this.props.labelOn : this.props.labelOff
            )
            );
    }
});

module.exports = CheckboxWithLabel; 

@jeffchan was right. The all of the required code is run through the preprocessor, not just the JSX files.

Looks like the fastest solution will be to use gulp, watchify and react to only process the changed JSX files while your working. We will then be able to specify only the tests that I want to run as well. This way the JSX files only get processed once and I have control over which tests are run. Something like this would be really nice for a testing workflow.

gulp jest --tests "Checkbox*,*Form*"

Watchify will then watch for any changes that these tests depend on, and then only process the changes and then only run the tests I'm working with.

@iamrandys I 100% agree with you. Jest and React are awesome, but compilation of JSX into JS is a big hinderance. Just curious how Gulp will solve the problem of having your required files (Non JSX) being run through the JSX preprocessor? Are you suggesting something like the following -http://blog.avisi.nl/2014/04/25/how-to-keep-a-fast-build-with-browserify-and-reactjs/ ?

Yep, I'm thinking about some kind of caching layer with the gulp plugin in
working on

On 11 August 2014 08:35, Tyrone Avnit [email protected] wrote:

@iamrandys https://github.com/iamrandys I 100% agree with you. Jest and
React are awesome, but compilation of JSX into JS is a big hinderance. Just
curious how Gulp will solve the problem of having your required files (Non
JSX) being run through the JSX preprocessor? Are you suggesting something
like the following? -
http://blog.avisi.nl/2014/04/25/how-to-keep-a-fast-build-with-browserify-and-reactjs/
?


Reply to this email directly or view it on GitHub
https://github.com/facebook/jest/issues/116#issuecomment-51749798.

Exactly, using gulp and watchify is amazingly fast with react. Throw in
gulp-livereload to refresh your browser after each change and you have an
amazing development environment. You make any change, save and you almost
instantly see the changes in all your open browsers and all devices. Now I
just need the same thing for my TDD.

It's about like this, but use reactify instead of hbsfy.
https://gist.github.com/benhowdle89/9533185

On Mon, Aug 11, 2014 at 2:35 AM, Tyrone Avnit [email protected]
wrote:

@iamrandys https://github.com/iamrandys I 100% agree with you. Jest and
React are awesome, but compilation of JSX into JS is a big hinderance. Just
curious how Gulp will solve the problem of having your required files (Non
JSX) being run through the JSX preprocessor? Are you suggesting something
like the following? -
http://blog.avisi.nl/2014/04/25/how-to-keep-a-fast-build-with-browserify-and-reactjs/
?


Reply to this email directly or view it on GitHub
https://github.com/facebook/jest/issues/116#issuecomment-51749798.

Thanks @iamrandys. Developed a quick react-component-boilerplate which uses Mocha and Chai (Jasmine can be easily substituted). Tests are extremely quick and you get the added benefit of Livereload. Use as you wish.

Either way, I really really need my tests to be fast for my workflow. I still need to figure out how to at least run a single suite. In jasmine I could use "ddescribe" or "iit" instead of "describe" and "it" to run a single test or suite. Jest is SO nice, I just need a fast workflow now.

You can definitely write it.only and I believe you can do describe.only as well.

Karma does exactly what you are wanting and all you have to do is add a
karma.conf file to your project. I didn't realize karma supported reactify
and browserify. Now you can test in all of your browsers at the same time.
I created a PR for your boilerplate project.

https://github.com/iamrandys/react-component-boilerplate/tree/karma

Just run 'npm test' and karma will launch your browsers and will watch for
changes.

On Tue, Aug 12, 2014 at 10:35 AM, Tyrone Avnit [email protected]
wrote:

Thanks @iamrandys https://github.com/iamrandys. Developed a quick
react-component-boilerplate
https://github.com/TYRONEMICHAEL/react-component-boilerplate which uses
Mocha and Chai (Jasmine can be easily substituted). Tests are extremely
quick and you get the added benefit of Livereload. Use as you wish.


Reply to this email directly or view it on GitHub
https://github.com/facebook/jest/issues/116#issuecomment-51931532.

Use the following preprocessor.js to avoid JSX-transforming non-JSX files. As is, it only processes .jsx files that contain the /** @jsx prefix. If you want to JSX-transform .js files, just remove the first part of the if-condition before the || (so that only the src.slice ... condition remains).

// from http://facebook.github.io/jest/docs/tutorial-react.html
var ReactTools = require('react-tools');
var MAGIC = "/** @jsx";
module.exports = {
  process: function(src, file) {
    if (!/\.jsx$/.test(file) || src.slice(0, MAGIC.length) != MAGIC) return src;
    return ReactTools.transform(src);
  }
};

Still kinda slow, though.

Interesting snippet @sqs. Correct me If I am wrong, but would it still not have to look through the each file and check if it needs to convert it? I have had much success with the following - react-component-boilerplate. Tests actually run pretty quickly.

Very nice. This reduced the time from 9.3s to 4.7s. This is for a single test. I'll still have to stay with Karma where it is much faster (100 tests take less than a second). Plus, Karma will watch for changes as you work and will test your code in multiple browsers, but I love Jest's automatic mocking though. Manually creating spies using rewireify is extra work, but you do have complete control.

Yeah, I may be misunderstanding you, but that's what I meant about removing the check for .jsx if you have .js files with jsx and want to detect based on the pragma header.

Sent from my iPhone

On Aug 28, 2014, at 23:45, Tyrone Avnit [email protected] wrote:

Interesting snippet @sqs. Correct me If I am wrong, but would it still not have to look through the each file and check if it needs to convert it? I have had much success with the following - react-component-boilerplate. Tests actually run pretty quickly.


Reply to this email directly or view it on GitHub.

Hi! I'm working on --watch for jest and generally trying to make this go faster. Will report back soon.

the first run for me takes about 5s (I just have one test, I'm just getting started). After that each additional run takes about 1.2-1.5s.

It looks like a decent amount of that time is spent loading the haste cache (which for my project is already a 4 meg file.

I'm looking forward to the --watch work, but I'm also wondering what is going on that requires 1.2 seconds of load time to run a test? I don't know anything about what haste is doing and why jest is using it, so I'm pretty clueless.

Haste supports a flavor of CommonJS module format were the module names are top-level rather than relative. That means we need to know the modules (and dependancies) ahead of time before running the program otherwise it would be incredibly inefficient to traverse the filesystem to look for a module on each require. However we realize that most people are using relative module format (a la node.js) and we want to remove the implicit dependency on Haste (unless an option is provided) and this should make it faster.

@amasad that sounds great. I've tried out intern.js and it runs a regular unit test from cmd line to finish in a few ms. Do you think jest could get to that fast? And have you considered extracting the automocking portion so that it is usable in other frameworks like jasmine or mocha?

I have found requiring files (especially 'react/addons' & the module being tested) once under the describe callback, instead of repeatedly in beforeEach or it callbacks makes a huge difference.

Obviously, I'm using coffee-script and not jsx, but this saves both preprocessor work and jest working to auto mock require calls.

__tests__/login_fields.coffee (3.013s) (ouch!)

describe 'Login Fields', -> 
 beforeEach ->
    {TestUtils} = require('react/addons').addons
    LoginFields = require '../login_fields'
    ...
  it 'should have left animation states defined', ->
    {TestUtils} = require('react/addons').addons
    ...
  it 'should have a translateX value equal to enterStateStart.left', ->
    {TestUtils} = require('react/addons').addons
    ...
  it 'should call handleLogin on button click or enter press with the entered username and password', ->
    {TestUtils} = require('react/addons').addons
    ...
  it 'should call updateFields on all change events', ->
    {TestUtils} = require('react/addons').addons
    ...

but, it gets much faster with...
__tests__/login_fields.coffee (0.604s) (not bad)

describe 'Login Fields', ->
  {TestUtils} = require('react/addons').addons
  LoginFields = require '../login_fields'
  # require other repeatedly needed modules here as well

  beforeEach ->
    # now you can use TestUtils to renderIntoDocument LoginFields here

  it 'should have left animation states defined', ->
    # and use TestUtils here
  ...

My tests are at 14 seconds long, even after using all of the optimizations recommended this far. Even with 16GB RAM and SSD. Jest is totally unusable in its current state. Sorry, switching to Karma.

I've found great success with karma, mocha, chai, sinon, rewireify and aliasify. Over 300 tests run in 1/2 a second. Best of all React is AMAZING!!!!! The team LOVES it and have been developing some really good stuff with it. It's so clean and maintainable. Huge difference from anything we've ever used.

Just ran into this myself. Tests run _REALLY_ slow. Problem with slow tests is that developers disable them or only run them part of the time. Any idea what is causing this? How can I help?

I had this exact issue - tests took about 17 seconds to run initially, and then 4 seconds after caching. It turns out that my build directory and external modules were not properly excluded. Setting the testPathDirs config option to point to the source directory reduced runtimes to 0.5 seconds.

This worked for me using React v0.12+:

var ReactTools = require('react-tools');


module.exports = {
  process: function(src, file) {
    if(!file.match(/\.react\.js$/)) return src;

    return ReactTools.transform(src);
  }
};

Just started using Jest as well - just testing regular JavaScript modules (no JSX / React) and Jest is nasty slow. I love the idea of inline tests and built-in mocking, but it's so painfully slow it makes me miss Mocha. I'm not sure what the culprit is... it's not searching the directory tree that's causing the slow speed. If I specify the file directly, it's still super slow.

Any ideas on at least the cause of the slowness? (I'm not using JSX / CoffeeScript; auto-mocking is turned off)

The original example never worked for me as the first argument always returned true.

var ReactTools = require('react-tools');
var MAGIC = "/** @jsx ";
module.exports = {
  process: function(src, file) {
    if (src.slice(0, MAGIC.length) != MAGIC) return src;
    return ReactTools.transform(src);
  }
};

@culshaw @haihappen thanks for the nice workarounds, shorten the 10s+ tests to 2+. this workarounds made me think that maybe we should use the extension _.jsx/_.react.js for our react files, i think it might help too when using reactify.

To be honest going through Grunt I was still getting times of +20s, got
React working with Karma and total time is about +4/5 secs.

All inside a VM though

Just to report back on this. We have been testing react with Karma/Mocha and we are close to 700 tests and it takes about 4 seconds to run all of the tests. We do have to mange mocks, but it's worth it. React has been AMAZING. Flawless and refreshingly stable. Game changer! Our team couldn't imaging using anything else.

I didn't ever get Jest to be fast. I am using mocha. If Jest was fast, I
would have used it instead.

On Thu, Feb 5, 2015 at 12:17 PM, Gil Birman [email protected]
wrote:

@iamrandys https://github.com/iamrandys would you mind explaining in
more detail how you managed to make jest so fast?


Reply to this email directly or view it on GitHub
https://github.com/facebook/jest/issues/116#issuecomment-73097182.

Thanks @iamrandys I had deleted my "how did you get jest to be fast?" question after realizing I had misread your post (but you responded at the same time)... anyway, it's a shame, I guess jest should still be considered not so ready for production use.

the workarounds/changes by @haihappen and @darcyadams helped me get the test time down from 3,5 sec to about 1 sec for a single test. That does not take into account the apparent startup time, which seems to be about 1 sec also. This seems much too slow to be efficient in daily work, so I guess I'll have a look at the mocha/karma combo. I like Jest's philosophy of mocking everything by default, but the benefit just is not there atm.

I have the same problem: I got just 3 tests in a small project and they take 3 seconds.

Is improving the performance anywhere near on the project roadmap?

BTW: I found a (pretty hackish) way to re-run unit tests only for files that have changed. This makes them pretty fast again, as usually there is only one test to run. I put it here: https://gist.github.com/mik01aj/fefb7718331e5454b9d1

Strange Jest was not mentioned at the React.js 2015 conf.

testPathDirs appears to be the culprit. Specify like this in package.json:

  "jest": {
    "unmockedModulePathPatterns": [
      "./node_modules"
    ],
    "scriptPreprocessor": "./preprocessor.js",
    "testDirectoryName": "tests",
    "testPathDirs": ["tests"]
  }

@adjavaherian be careful with that if you're using automatic mocking: https://github.com/facebook/jest/issues/176

In fact, expect auto-mocking to break in subtle and frustrating ways if your testPathDirs doesn't cover your dependencies.

These concerns makes me think we might be doing something wrong with our test set-up. I might be wrong here, but as far as I know, we're all using stuff like: var component = React.createFactory(require("component/path")) along with other required modules within beforeEach test. Surely this mustn't be necessary for all tests. I mean a factory should produce a fresh component every time. If I move the require outside of the beforeEach block test speed increases 10x. Unfortunately, in that case, some tests oddly fail and I don't know why.

Not sure if this helps. Thoughts?

would be nice if preprocessing time was left out of reported test execution time. Kind of unfair to see red when the bulk of that work comes from a transformation step.

Hi guys,

I´m having the same problem. I even have some test cases which take around 1min to run :(

I don´t know where to start to profile the performance issue, any hint ?


UPDATE

I fixed this problem that only appeared in my VM environment (cf : http://stackoverflow.com/a/13703132). Now tests are still slower than what I would expect but way faster than before the vagrant fix ( 60 seconds -> 6 seconds for my test suit)

If speed is still an issue, I suggest moving to Mocha. We have had a lot of success with this fork, which explains how to setup tests for simple to complex React deployments. https://github.com/adjavaherian/mocha-react We regularly run over a 100 tests in about 3 seconds.

I agree Mocha is the way to go. Up to almost 900 tests and it takes about 4 seconds.

On Apr 23, 2015, at 4:53 PM, Amir Djavaherian [email protected] wrote:

If speed is still an issue, I suggest moving to Mocha. We have had a lot of success with this fork, which explains how to setup tests for simple to complex React deployments. https://github.com/adjavaherian/mocha-react We regularly run over a 100 tests in about 3 seconds.


Reply to this email directly or view it on GitHub.

Same experience, I just set up Jest with only one test (using JSX) and it takes about 3 seconds, this is a lot.

@iamrandys do you mind showing an example of your setup? Seems like the perfect combo.

@amasad Is there an option with Jest to build up a cache for compiled files similar to what the babel-loader allows in the cacheDirectory option? - https://github.com/babel/babel-loader#options

What makes jest slow for me isn't the compilation but rather the startup of the worker pool processes. All my test pass in under 0.05 seconds except the first ones, which take around 4 seconds.
https://github.com/jeffmo/node-worker-pool
https://github.com/facebook/jest/blob/master/src/TestRunner.js#L376

@songawee It doesn't but want to send a PR to have it as an option? I don't think we should have it on by default because it's sometimes impossible to know when to break the cache. For example, if you change your compiler options, the cache should reset. Another option is to have a reset-cache option in addition to caching.

@doodzik are you sure it's the worker-pool and not the node-haste stating and reading of modules?

@amasad What I did was to measured the time each step in running jest took for completion.
And the node-worker-pool was the last instance where the tests were slow.
It could be that my findings are just the symptom and not the root of the problem.
But I hadn't had time to give it a proper analysis.

My tests currently look like this:
screen shot 2015-06-03 at 00 10 16

My react tests are slow(the ones in the examples folder). What I'm talking about are the non react tests.

+1

Same here. Tests are very very slow :disappointed:

I thought It was only me that faced the issue. It is my first time using Jest and I don't get fast test result, either. Wondering how Facebook do the test using Jest?

My question about Jest improvements to the React guys at React Europe conference Q&A session - https://youtu.be/CRJZBZ_-6hQ?t=363

Switched to Mocha + Sinon. Never been happier.

On 31 August 2015 at 17:45, Alan Rubin [email protected] wrote:

My question about Jest to the React guys at React Europe conference Q&A
session - https://youtu.be/CRJZBZ_-6hQ?t=363


Reply to this email directly or view it on GitHub
https://github.com/facebook/jest/issues/116#issuecomment-136394910.

I have the same problem. Jest tests just take a lot of time and the execution time actually varies. Whether to run them in parallel or in just one process (--runInBand) did not matter. It appears to not be a resource contention between the worker processes.

I created some cpu dumps with the v8 profiler (https://github.com/node-inspector/v8-profiler) and found that most time appears to be spent mocking modules. I.e. 25% of the execution time of my unit test is spent in jest-cli/src/lib/utils.js#runContentWithLocalBindings.

any performance updates? just picked up jest with es6 and babel-jest, but running 2 simple tests in > 10 seconds :-(
tried a lot of ideas from this thread to speed up, but nothing worked...

We'll be focusing on this soon. We are a little swamped with work on jest right now but we are committed to make it more awesome.

Are there any tasks the community could help with?

+1

The biggest help right now would actually be improving the documentation, website and going through issues and helping out people in open source.

One thing we have done to speed our JEST tests up in the build pipeline was to replace our single core machine with a multi core one. By default jest spawns as many workers as hardware threads are available. If this is not available to you you can manually play with '-w' (maxWorkers). You may gain a speedup also on a single core.

Ultimately we found that mocking modules is very costly (see my comment above) and causes a majority of the execution time.

Jest with es6 for me is completely unusable. it takes 10+ seconds just to start up, and then it takes 2s to run the single test I have at the moment. I was expecting a lot more, switching back to karma :(

We are currently working on replacing node-haste with a new module resolver, which should fix this issue.

Hi all. Is there any news on this issue ?

Hi, is Jest suitable for non React testing? Would like to have a common standard for both react and non-react apps in our team.

Jest is a universal test-runner and you are in no way required to use React. :) Just take a look at one of the examples!

Hi all, some real interesting info on here. I'm also experiencing issues with tests running slow too. I've currently got 13 tests taking ~15secs to run.

I did find adding "testPathDirs": ["<rootDir>/path/to/tests/"] to our packages.json file helped to improve the startup time considerably.

@cpojer Have you got an update for us regarding the new and improved module resolver? I'm really hoping that this is going to be the key to getting tests running much quicker

This work is happening in #599.

Thanks @cpojer 😀
I look forward to seeing the finished Haste2

The same tests using mocha run in 44ms for me where jest took full 6 seconds.

It took me about 15 minutes to switch my initial 6 test files using jest to using Mocha, jsdom and sinon.

Good news everyone, I'm merging #599 today and it should do away with the slow startup, finally.

Ok, this should finally be fixed in Jest 0.9. Sorry that this took so long but there was some clowniness in Jest :)

See https://github.com/facebook/react/pull/6052 on how the React tests themselves were sped up. If you'd like to try this improvement, check out the comments in #599. It is currently tagged as jest-cli@next until to see if there are any bugs that people in open source might encounter. I'll close this issue as resolved.

npm install jest-cli@next if you want to run this new version (rather than jest@next @cpojer)

oh yeah, I always make this mistake :) I edited my original comment.

@cpojer after upgrading using npm install jest-cli@next I'm having problems specifying dontMock. By which I mean, before the update (using [email protected]) this line works properly:

jest.dontMock('../../../../fixtures');

then after the update to 0.9.0, the same call results in the module being mocked

@steinbachr that should probably go into a separate issue. Would be great if you could provide a repro, haven't seen this issue come up at FB!

thanks @cpojer, issue created here

Was this page helpful?
0 / 5 - 0 ratings