Skip to content

Commit

Permalink
Assign each worker a worker id in parallel mode.
Browse files Browse the repository at this point in the history
This uses a new feature from the workerpool module, which allows
overriding process parameters for each process, which is why the
workerpool module has been updated to the latest version (6.2.0).
  • Loading branch information
forty committed Jan 17, 2022
1 parent baa12fd commit aae81f9
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 9 deletions.
4 changes: 4 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,10 @@ Free-tier cloud CI services may not provide a suitable multi-core container or V

It's unlikely (but not impossible) to see a performance gain from a [job count](#-jobs-count-j-count) _greater than_ the number of available CPU cores. That said, _play around with the job count_--there's no one-size-fits all, and the unique characteristics of your tests will determine the optimal number of jobs; it may even be that fewer is faster!

### Parallel Mode Worker IDs

Each process launched by parallel mode is assigned a unique id, from 0 for the first process to be launched, to N-1 for the Nth process. This worker id may be accessed in tests via the environment variable `MOCHA_WORKER_ID`. It can be used for example to assign a different database, service port, etc for each test process.

## Root Hook Plugins

> _New in v8.0.0_
Expand Down
18 changes: 17 additions & 1 deletion lib/nodejs/buffered-worker-pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,23 @@ class BufferedWorkerPool {
process.execArgv.join(' ')
);

this.options = {...WORKER_POOL_DEFAULT_OPTS, opts, maxWorkers};
let counter = 0;
const onCreateWorker = ({forkOpts}) => {
return {
forkOpts: {
...forkOpts,
// adds an incremental id to all workers, which can be useful to allocate resources for each process
env: {...process.env, MOCHA_WORKER_ID: counter++}
}
};
};

this.options = {
...WORKER_POOL_DEFAULT_OPTS,
...opts,
maxWorkers,
onCreateWorker
};
this._pool = workerpool.pool(WORKER_PATH, this.options);
}

Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"strip-json-comments": "3.1.1",
"supports-color": "8.1.1",
"which": "2.0.2",
"workerpool": "6.1.5",
"workerpool": "6.2.0",
"yargs": "16.2.0",
"yargs-parser": "20.2.4",
"yargs-unparser": "2.0.0"
Expand Down
7 changes: 7 additions & 0 deletions test/integration/fixtures/parallel/testworkerid1.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {describe, it} from '../../../../index.js';

describe('test1', () => {
it('should fail', () => {
throw new Error(`MOCHA_WORKER_ID=${process.env.MOCHA_WORKER_ID}`);
});
});
7 changes: 7 additions & 0 deletions test/integration/fixtures/parallel/testworkerid2.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {describe, it} from '../../../../index.js';

describe('test2', () => {
it('should fail', () => {
throw new Error(`MOCHA_WORKER_ID=${process.env.MOCHA_WORKER_ID}`);
});
});
7 changes: 7 additions & 0 deletions test/integration/fixtures/parallel/testworkerid3.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import {describe, it} from '../../../../index.js';

describe('test3', () => {
it('should fail', () => {
throw new Error(`MOCHA_WORKER_ID=${process.env.MOCHA_WORKER_ID}`);
});
});
38 changes: 38 additions & 0 deletions test/integration/parallel.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,42 @@ describe('parallel run', () => {
assert.strictEqual(result.stats.failures, 1);
assert.strictEqual(result.stats.passes, 2);
});

it('should correctly set worker ids for each process', async () => {
const result = await runMochaJSONAsync('parallel/testworkerid3.mjs', [
'--parallel',
'--jobs',
'2',
require.resolve('./fixtures/parallel/testworkerid1.mjs'),
require.resolve('./fixtures/parallel/testworkerid2.mjs')
]);
// test 1 always runs on worker 0
assert.strictEqual(
result.tests.filter(
test =>
test.fullTitle === 'test1 should fail' &&
test.err.message === 'MOCHA_WORKER_ID=0'
).length,
1
);
// test 2 always runs on worker 1
assert.strictEqual(
result.tests.filter(
test =>
test.fullTitle === 'test2 should fail' &&
test.err.message === 'MOCHA_WORKER_ID=1'
).length,
1
);
// test 3 may run on either worker 0 or 1 (as jobs = 2)
assert.strictEqual(
result.tests.filter(
test =>
test.fullTitle === 'test3 should fail' &&
(test.err.message === 'MOCHA_WORKER_ID=0' ||
test.err.message === 'MOCHA_WORKER_ID=1')
).length,
1
);
});
});

0 comments on commit aae81f9

Please sign in to comment.