Skip to content

Commit

Permalink
Make Jest’s Test Runner configurable. (jestjs#4240)
Browse files Browse the repository at this point in the history
  • Loading branch information
cpojer authored Aug 10, 2017
1 parent 437b822 commit 43cec0a
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ exports[`--showConfig outputs config info and exits 1`] = `
\\"roots\\": [
\\"<<REPLACED_ROOT_DIR>>\\"
],
\\"runner\\": \\"jest-runner\\",
\\"setupFiles\\": [],
\\"snapshotSerializers\\": [],
\\"testEnvironment\\": \\"jest-environment-jsdom\\",
Expand Down
2 changes: 1 addition & 1 deletion packages/jest-cli/src/run_jest.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ const runJest = async ({

const results = await new TestScheduler(globalConfig, {
startRun,
}).runTests(allTests, testWatcher);
}).scheduleTests(allTests, testWatcher);

sequencer.cacheResults(allTests, results);

Expand Down
75 changes: 58 additions & 17 deletions packages/jest-cli/src/test_scheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ import VerboseReporter from './reporters/verbose_reporter';

const SLOW_TEST_TIME = 3000;

// The default jest-runner is required because it is the default test runner
// and required implicitly through the `runner` ProjectConfig option.
TestRunner;

export type TestSchedulerOptions = {|
startRun: (globalConfig: GlobalConfig) => *,
|};
Expand All @@ -39,12 +43,10 @@ class TestScheduler {
_dispatcher: ReporterDispatcher;
_globalConfig: GlobalConfig;
_options: TestSchedulerOptions;
_testRunner: TestRunner;

constructor(globalConfig: GlobalConfig, options: TestSchedulerOptions) {
this._dispatcher = new ReporterDispatcher();
this._globalConfig = globalConfig;
this._testRunner = new TestRunner(globalConfig);
this._options = options;
this._setupReporters();
}
Expand All @@ -57,7 +59,7 @@ class TestScheduler {
this._dispatcher.unregister(ReporterClass);
}

async runTests(tests: Array<Test>, watcher: TestWatcher) {
async scheduleTests(tests: Array<Test>, watcher: TestWatcher) {
const onStart = this._dispatcher.onTestStart.bind(this._dispatcher);
const timings = [];
const contexts = new Set();
Expand Down Expand Up @@ -138,20 +140,36 @@ class TestScheduler {
showStatus: !runInBand,
});

try {
await this._testRunner.runTests(
tests,
watcher,
onStart,
onResult,
onFailure,
{
serial: runInBand,
},
);
} catch (error) {
if (!watcher.isInterrupted()) {
throw error;
const testRunners = Object.create(null);
contexts.forEach(({config}) => {
if (!testRunners[config.runner]) {
// $FlowFixMe
testRunners[config.runner] = new (require(config.runner): TestRunner)(
this._globalConfig,
);
}
});

const testsByRunner = this._partitionTests(testRunners, tests);

if (testsByRunner) {
try {
for (const runner of Object.keys(testRunners)) {
await testRunners[runner].runTests(
testsByRunner[runner],
watcher,
onStart,
onResult,
onFailure,
{
serial: runInBand,
},
);
}
} catch (error) {
if (!watcher.isInterrupted()) {
throw error;
}
}
}

Expand All @@ -174,6 +192,29 @@ class TestScheduler {
return aggregatedResults;
}

_partitionTests(
testRunners: {[key: string]: TestRunner},
tests: Array<Test>,
) {
if (Object.keys(testRunners).length > 1) {
return tests.reduce((testRuns, test) => {
const runner = test.context.config.runner;
if (!testRuns[runner]) {
testRuns[runner] = [];
}
testRuns[runner].push(test);
return testRuns;
}, Object.create(null));
} else if (tests.length > 0 && tests[0] != null) {
// If there is only one runner, don't partition the tests.
return Object.assign(Object.create(null), {
[tests[0].context.config.runner]: tests,
});
} else {
return null;
}
}

_shouldAddDefaultReporters(reporters?: Array<ReporterConfig>): boolean {
return (
!reporters ||
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ module.exports = ({
preset: null,
resetMocks: false,
resetModules: false,
runner: 'jest-runner',
snapshotSerializers: [],
testEnvironment: 'jest-environment-jsdom',
testFailureExitCode: 1,
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ const getConfigs = (
resolver: options.resolver,
rootDir: options.rootDir,
roots: options.roots,
runner: options.runner,
setupFiles: options.setupFiles,
setupTestFrameworkScriptFile: options.setupTestFrameworkScriptFile,
skipNodeResolution: options.skipNodeResolution,
Expand Down
1 change: 1 addition & 0 deletions packages/jest-config/src/normalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ function normalize(options: InitialOptions, argv: Argv) {
break;
case 'moduleLoader':
case 'resolver':
case 'runner':
case 'setupTestFrameworkScriptFile':
case 'testResultsProcessor':
case 'testRunner':
Expand Down
5 changes: 5 additions & 0 deletions packages/jest-runner/src/run_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ import {
getConsoleOutput,
setGlobal,
} from 'jest-util';
import jasmine2 from 'jest-jasmine2';
import {getTestEnvironment} from 'jest-config';
import docblock from 'jest-docblock';

// The default jest-runner is required because it is the default test runner
// and required implicitly through the `testRunner` ProjectConfig option.
jasmine2;

function runTest(
path: Path,
globalConfig: GlobalConfig,
Expand Down
1 change: 1 addition & 0 deletions test_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const DEFAULT_PROJECT_CONFIG: ProjectConfig = {
resolver: null,
rootDir: '/test_root_dir/',
roots: [],
runner: 'jest-runner',
setupFiles: [],
setupTestFrameworkScriptFile: null,
skipNodeResolution: false,
Expand Down
5 changes: 4 additions & 1 deletion types/Config.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export type DefaultOptions = {|
preset: ?string,
resetMocks: boolean,
resetModules: boolean,
runner: string,
snapshotSerializers: Array<Path>,
testEnvironment: string,
testFailureExitCode: string | number,
Expand Down Expand Up @@ -105,6 +106,7 @@ export type InitialOptions = {
resolver?: ?Path,
rootDir: Path,
roots?: Array<Path>,
runner?: string,
scriptPreprocessor?: string,
setupFiles?: Array<Path>,
setupTestFrameworkScriptFile?: Path,
Expand All @@ -115,8 +117,8 @@ export type InitialOptions = {
testFailureExitCode?: string | number,
testMatch?: Array<Glob>,
testNamePattern?: string,
testPathIgnorePatterns?: Array<string>,
testPathDirs?: Array<Path>,
testPathIgnorePatterns?: Array<string>,
testRegex?: string,
testResultsProcessor?: ?string,
testRunner?: string,
Expand Down Expand Up @@ -197,6 +199,7 @@ export type ProjectConfig = {|
resolver: ?Path,
rootDir: Path,
roots: Array<Path>,
runner: string,
setupFiles: Array<Path>,
setupTestFrameworkScriptFile: ?Path,
skipNodeResolution: boolean,
Expand Down

0 comments on commit 43cec0a

Please sign in to comment.