Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Slow React Tests #116

Closed
TYRONEMICHAEL opened this issue Aug 8, 2014 · 81 comments
Closed

Slow React Tests #116

TYRONEMICHAEL opened this issue Aug 8, 2014 · 81 comments

Comments

@TYRONEMICHAEL
Copy link

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?

@gothy
Copy link

gothy commented Aug 8, 2014

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? :)

@TYRONEMICHAEL
Copy link
Author

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

@gothy
Copy link

gothy commented Aug 8, 2014

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 :)

@TYRONEMICHAEL TYRONEMICHAEL changed the title Slow Tests Slow React Tests Aug 8, 2014
@jeffchan
Copy link

jeffchan commented Aug 8, 2014

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.

@hojberg
Copy link

hojberg commented Aug 8, 2014

I definitely also experience slow tests with jest :(

@iamrandys
Copy link

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');

@TYRONEMICHAEL
Copy link
Author

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

@TYRONEMICHAEL
Copy link
Author

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.

@iamrandys
Copy link

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; 

@iamrandys
Copy link

@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.

@TYRONEMICHAEL
Copy link
Author

@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/ ?

@Dakuan
Copy link
Contributor

Dakuan commented Aug 11, 2014

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 notifications@github.com 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
#116 (comment).

@iamrandys
Copy link

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 notifications@github.com
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
#116 (comment).

@TYRONEMICHAEL
Copy link
Author

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.

@sophiebits
Copy link
Contributor

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.

@iamrandys
Copy link

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 notifications@github.com
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
#116 (comment).

@sqs
Copy link

sqs commented Aug 29, 2014

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.

@TYRONEMICHAEL
Copy link
Author

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.

@iamrandys
Copy link

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.

@sqs
Copy link

sqs commented Aug 29, 2014

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 notifications@github.com 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.

@amasad
Copy link
Contributor

amasad commented Sep 10, 2014

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

@aaronjensen
Copy link
Contributor

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.

@amasad
Copy link
Contributor

amasad commented Sep 21, 2014

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.

@aaronjensen
Copy link
Contributor

@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?

@darcyadams
Copy link

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
  ...

@CodeOtter
Copy link

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.

@iamrandys
Copy link

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.

@kristoferjoseph
Copy link

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?

@deerawan
Copy link

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?

@alanrubin
Copy link

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

@gbbr
Copy link

gbbr commented Aug 31, 2015

Switched to Mocha + Sinon. Never been happier.

On 31 August 2015 at 17:45, Alan Rubin notifications@github.com 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
#116 (comment).

@hansman
Copy link

hansman commented Sep 15, 2015

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.

@cdreier
Copy link
Contributor

cdreier commented Oct 5, 2015

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...

@cpojer
Copy link
Member

cpojer commented Oct 5, 2015

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.

@clentfort
Copy link
Contributor

Are there any tasks the community could help with?

@hansman
Copy link

hansman commented Oct 5, 2015

+1

@cpojer
Copy link
Member

cpojer commented Oct 5, 2015

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

@hansman
Copy link

hansman commented Oct 5, 2015

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.

@fabiosussetto
Copy link

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 :(

@cpojer
Copy link
Member

cpojer commented Oct 16, 2015

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

@HenriJ
Copy link

HenriJ commented Dec 3, 2015

Hi all. Is there any news on this issue ?

@quantuminformation
Copy link

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.

@clentfort
Copy link
Contributor

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!

@SomniumDigital
Copy link

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

@cpojer
Copy link
Member

cpojer commented Jan 7, 2016

This work is happening in #599.

@SomniumDigital
Copy link

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

@srossross
Copy link

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.

@cpojer
Copy link
Member

cpojer commented Feb 16, 2016

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

@cpojer
Copy link
Member

cpojer commented Feb 17, 2016

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

See facebook/react#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.

@cpojer cpojer closed this as completed Feb 17, 2016
@SomniumDigital
Copy link

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

@cpojer
Copy link
Member

cpojer commented Feb 17, 2016

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

@steinbachr
Copy link

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

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

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

@cpojer
Copy link
Member

cpojer commented Feb 24, 2016

@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!

@steinbachr
Copy link

thanks @cpojer, issue created here

@github-actions
Copy link

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests