-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
[RFC] Multi project runner #3156
Conversation
I would like to take a moment to celebrate. Please take a look at my afternoon's journey through the attached diffs. This issue has been on my mind for an entire year now and is a result of all the work that went into Jest by all of you, the community members as well as the countless discussions I had about this with @DmitriiAbramov. I finally made a breakthrough over the last couple of weeks after being forced by @ljharb (and some other people who insulted me) to organize my thoughts. I couldn't have done it without you. I was also guided only by Flow and prettier (which is an amazing workflow, btw.) and did an occasional sanity check that Jest wasn't broken on the way. After I was done with the last line of code after a couple hours of intense focus, everything worked on the first try. I'm happy, given that I haven't written any real code in months. 🎉 |
I hope I didn't insult you! :-) (if so, my apologies) |
Not at all! Appreciate any of your comments, please do it more often. |
65488b3
to
07acc0c
Compare
RFC updated. All tests are passing with this and there are no more major issues but there is a lot of work that still needs to be done before we should ship it. The changes up to now fix a number of things on top of the initial RFC:
More TODOs:
Note: I'm getting married this week and will be on my honeymoon soon, so it'll be a while until this diff is done. I do appreciate intermediate reviews up until this point though as well as suggestions if this could be broken up into smaller pieces, something I currently can't conceive. Nevertheless, this diff isn't as big as I thought it would be. Also happy if anybody wants to build on top of this PR to work on any of the TODOs that I outlined. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked at half of it, I'll finish it tomorrow 😄
packages/jest-cli/src/cli/runCLI.js
Outdated
if (argv.debug) { | ||
logDebugMessages(config, pipe); | ||
// TODO fix/remove this: there should be a `--show-config` argument. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have a ticket tracking this? I'm happy to add the arg if needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also could make a checklist under #2970 and treat it as an umbrella task
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before merging anything, I'll get rid of all the inline TODOs at least. Thanks for pointing it out.
@@ -30,7 +30,7 @@ jest.mock('../TestWorker', () => {}); | |||
jest.mock('../reporters/DefaultReporter'); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have tests for "multi contexts" test runs?
packages/jest-cli/src/cli/runCLI.js
Outdated
if (argv.watch || argv.watchAll) { | ||
const {config} = configs[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why only the first config? Don't we need to pass all of them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I just read your todo comment
Make watch mode work with this. I wanted to get to a MVP asap, so I left this one alone for now.
Are we thinking of adding a way to specify projects that are in the same root but that use different config?
Or would I need to trick Jest by nesting each config into its own directory and then setting the root of them to |
Codecov Report
@@ Coverage Diff @@
## master #3156 +/- ##
==========================================
+ Coverage 65.02% 65.04% +0.02%
==========================================
Files 177 178 +1
Lines 6510 6537 +27
Branches 4 4
==========================================
+ Hits 4233 4252 +19
- Misses 2276 2284 +8
Partials 1 1
Continue to review full report at Codecov.
|
Pulling things out of this PR to make the things I add on top of the existing code easier to review over time: #3289 |
8057960
to
1f900d0
Compare
packages/jest-cli/src/cli/runCLI.js
Outdated
// TODO | ||
configs[0].hasDeprecationWarnings, | ||
); | ||
if (hasDeprecationWarnings) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, this is so much nicer
Done:
Todo:
Follow-up before Jest 20, but shouldn't block this PR (it would get way too big):
|
Wonder if this commit |
d6b4e2e
to
8ecccf5
Compare
Alright, the two other diffs were pulled out and are merged and we are fully rebased. Now we are back down to a manageable +500 -500 diff :) |
contexts.forEach(context => { | ||
const status = snapshot.cleanup( | ||
context.hasteFS, | ||
this._config.updateSnapshot, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think in the end we would like to use context.config.updateSnapshot
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nvm, discard that comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think separating the config into sharedConfig
and projectConfig
is really important on this stage.
If we don't do it now, we might end up with a lot of leaky abstractions or modules that have way too much context on the outside world.
Having a simple external api (and probably a single config for both shared
and project
values for the end used) but having a hard separation once it gets into jest-config
module into two separate configs seems to be the way to go.
packages/jest-cli/src/runJest.js
Outdated
sequencer.cacheResults(tests, results); | ||
const allTests = testRunData | ||
.reduce((tests, testRun) => tests.concat(testRun.tests), []) | ||
.sort((a: Test, b: Test) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this logic not inside TestSequencer
?
packages/jest-cli/src/runJest.js
Outdated
|
||
return data; | ||
}; | ||
|
||
const runJest = async ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you rewrite this function as something like this and take everything else out?
runJest = async (/* ... */) => {
const maxWorkers = getMaxWorkers(argv);
const testPathPattern = getTestPathPattern(argv);
const firstContext = contexts[0];
const testRunData = await getTestRunData(/*...*/);
const sortedTestsFromAllProjects = getSortedTestsFromAllProjects(/*...*/);
warnIfNoTestsFound(/*...*/);
setVerboseIfRunningOnlyOneTest(contexts);
const testResults = await runTests(/*...*/);
return processResults(testResults);
};
sorry :( very hard to review and read the code that has dozens of branches :(
packages/jest-cli/src/runJest.js
Outdated
const results = await new TestRunner( | ||
context.config, | ||
{ | ||
getTestSummary: () => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks like a leaky abstraction of SummaryReporter, is it possible to move it down the hierarchy and pass needed data?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i just realized that it was already there before, is it still possible to move it inside?
watch: config.watch, | ||
}); | ||
const hasteMapInstances = Array(configs.length); | ||
const contexts = await Promise.all( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
following our meeting discussion: we can put both sharedConfig
and projectConfig
in the context. i think
const chalk = require('chalk'); | ||
const {KEYS} = require('../constants'); | ||
|
||
module.exports = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you mind adding a line or two explaining why we need this? 🙂
the callsite doesn't really give any information either
this._estimatedTime = options.estimatedTime; | ||
} | ||
|
||
onRunComplete( | ||
contexts: Set<Context>, | ||
config: Config, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this going to be a config for project where the last test was run from?
this looks a little strange, since onRunComplete
seems to be responsible for summarizing the whole (multi-project) run and not having any dependencies on a specific project
Ok, addressed all of Dmitrii's concerns except the config split which we agreed we'll do in a follow-up. Also made the paths relative to This diff is now ready for a final review (minus some CI issue that I'll fix :) ). |
…jest-cli test run.
* Add `—experimentalProjects` to run multiple projects within the same jest-cli test run. * Improve the “no tests found” message for multiple projects. * Do not pass a single context to TestRunner and remove RunnerContext from reporters. * Rename `patternInfo` to `PathPattern` * Remove `hasDeprecationWarnings` from `watch` function, move it up one level. * Make watch mode work with multiple projects. * Refactor runJest and Reporters, show proper relative paths. * SearchSource now returns `tests: Array<Test>`. * Use one TestSequencer instance for all contexts. * Fix runJest-test. * Fix TestSequencer-test on Windows.
* Add `—experimentalProjects` to run multiple projects within the same jest-cli test run. * Improve the “no tests found” message for multiple projects. * Do not pass a single context to TestRunner and remove RunnerContext from reporters. * Rename `patternInfo` to `PathPattern` * Remove `hasDeprecationWarnings` from `watch` function, move it up one level. * Make watch mode work with multiple projects. * Refactor runJest and Reporters, show proper relative paths. * SearchSource now returns `tests: Array<Test>`. * Use one TestSequencer instance for all contexts. * Fix runJest-test. * Fix TestSequencer-test on Windows.
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Summary
Context: #2970
This diff is the initial RFC for the multi-project runner. This is the proposal that merges all functionality into jest-cli which will make Facebook's internal multi-runner obsolete. The initial draft changes the Jest CLI to operate on a list of
TestContext
s, which is a new name for HasteContexts with the configuration object added to it. This is basically the entire extent of the added complexity to make this work, the rest is refactors that should be made regardless.The refactoring of the TestSequencer, runCLI and usage of async/await alone make the codebase actually easier to understand and concerns are separated better with this diff applied. These changes were already landed as part of this PR.
TODO
Test plan
cd examples
jest --experimentalProjects */ --no-cache