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

Parallel options #2

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,11 @@ build/Release
# Deployed apps should consider commenting this line out:
# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
node_modules


# Webstorm IDE metadata directory
.idea

# test report files
test/report/*.xml*
test/report/*.log
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,53 @@ gulp.task('test-custom-mocha', function() {
- flags: mocha flags (default: none)
- liveOutput: print output direct to console
- errorSummary: show error summary (default: true)
- iterations: Array, see below

### Iterations

If you want to run parallel processes based on criteria other than files, use an iterations array.

The iterations array should contain whatever "Options" (see above) you wish to override for a given iteration.

The easiest to envision example would be:
* your test suite names are annotated as: @groupA@, @groupB@, @groupC@, and so on
* these groupings are spread across files, where a file may contain one or more suite of a given group
* you want to spawn a mocha process for each grouping

To achieve, you would specify an iterations array where each entry uses a different mocha grep. E.g. the task
example "test-mocha-opts-parallel" in this project's `gulpfile.js`.

```javascript
gulp.task('test-mocha-opts-parallel', function () {
function setEnv(envs) {
var env = process.env;
env = _.clone(env);
env = _.merge(env, envs, {JUNIT_REPORT_PATH: path.resolve(__dirname, 'test/report/report.xml')});
return env;
}
var opts = {
concurrency: 3,
flags: {R: 'mocha-jenkins-reporter'},
iterations: [{
env: setEnv({NODE_ENV: 'groupa'}),
flags: {grep: "@groupA@"}
}, {
env: setEnv({NODE_ENV: 'groupb'}),
flags: {grep: "@groupB@"}
}, {
env: setEnv({NODE_ENV: 'groupc'}),
flags: {grep: "@groupC@"}
}]
};
var mocha = mochaStream(opts);
gulp.src('test/group/*-specs.js')
.pipe(mocha);
});
```

Another use case might be if you are driving browser/device automation, and you want to run the same set of files
in parallel on several browser/device combinations.

## Todo

- concatenate mocha status at the end
Expand Down
85 changes: 58 additions & 27 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
"use strict";

var gulp = require('gulp'),
mochaStream = require('./lib').mochaStream,
SpawnMocha = require('./lib').SpawnMocha,
_ = require('lodash'),
through = require('through'),
Q = require('q'),
runSequence = Q.denodeify(require('run-sequence')),
assert = require('assert'),
File = require('vinyl'),
from = require('from');
mochaStream = require('./lib').mochaStream,
SpawnMocha = require('./lib').SpawnMocha,
_ = require('lodash'),
through = require('through'),
Q = require('q'),
runSequence = Q.denodeify(require('run-sequence')),
assert = require('assert'),
File = require('vinyl'),
path = require('path'),
from = require('from');

function customMocha(opts) {
opts = opts || {};
var spawnMocha = new SpawnMocha(opts);
var stream = through(function write(file) {
spawnMocha.add(file.path);
}, function() {});
}, function () {
});
var errors = [];
spawnMocha.on('error', function(err) {
spawnMocha.on('error', function (err) {
console.error(err.toString());
errors.push(err);
}).on('end', function() {
if(errors.length > 0) {
}).on('end', function () {
if (errors.length > 0) {
console.error('ERROR SUMMARY: ');
_(errors).each(function(err) {
_(errors).each(function (err) {
console.error(err);
console.error(err.stack);
}).value();
Expand All @@ -35,18 +37,19 @@ function customMocha(opts) {
return stream;
}

gulp.task('test-mocha', function() {
gulp.task('test-mocha', function () {
var startMS = Date.now();
var StdOutFixture = require('fixture-stdout');
var fixture = new StdOutFixture();
var output = '';
fixture.capture( function onWrite (string ) {
fixture.capture(function onWrite(string) {
output += string;

return false;
});
var mocha = mochaStream({concurrency: 10});
var srcFiles = [];
_(10).times(function() {
_(10).times(function () {
srcFiles.push(new File({
cwd: "/",
base: "test/",
Expand All @@ -56,21 +59,22 @@ gulp.task('test-mocha', function() {
return from(srcFiles)
.pipe(mocha)
.on('error', console.error)
.on('end', function() {
.on('end', function () {
fixture.release();
console.log(output);
// we should have run 10 tests in parallel in less than 10 sec
assert(output.match(/1 passing/g).length === 10);
assert( Date.now() - startMS < 5000);
assert(Date.now() - startMS < 5000);
});
});

gulp.task('test-custom-mocha', function() {
gulp.task('test-custom-mocha', function () {
return gulp.src('test/*-specs.js', {read: false})
.pipe(customMocha())
.on('error', console.error);
});

gulp.task('test-live-output', function() {
gulp.task('test-live-output', function () {
var mocha = mochaStream({liveOutput: true, concurrency: 1});
var srcFiles = [];
srcFiles.push(new File({
Expand All @@ -82,7 +86,7 @@ gulp.task('test-live-output', function() {
.pipe(mocha);
});

gulp.task('test-live-output-with-file', function() {
gulp.task('test-live-output-with-file', function () {
var mocha = mochaStream({
liveOutput: true,
fileOutput: '/tmp/out.log',
Expand All @@ -97,7 +101,7 @@ gulp.task('test-live-output-with-file', function() {
return from(srcFiles).pipe(mocha);
});

gulp.task('test-with-file', function() {
gulp.task('test-with-file', function () {
var mocha = mochaStream({
fileOutput: '/tmp/out.log',
concurrency: 1
Expand All @@ -112,12 +116,12 @@ gulp.task('test-with-file', function() {
});


gulp.task('test-live-output-with-prepend', function() {
gulp.task('test-live-output-with-prepend', function () {
var mocha = mochaStream({
liveOutput: true,
liveOutputPrepend: 'client --> ',
concurrency: 1,
flags: { R: "tap" }
flags: {R: "tap"}
});
var srcFiles = [];
srcFiles.push(new File({
Expand All @@ -129,14 +133,41 @@ gulp.task('test-live-output-with-prepend', function() {
.pipe(mocha);
});

gulp.task('test-mocha-opts-parallel', function () {
function setEnv(envs) {
var env = process.env;
env = _.clone(env);
env = _.merge(env, envs, {JUNIT_REPORT_PATH: path.resolve(__dirname, 'test/report/report.xml')});
return env;
}

var opts = {
concurrency: 3,
flags: {R: 'mocha-jenkins-reporter'},
iterations: [{
env: setEnv({NODE_ENV: 'groupa'}),
flags: {grep: "@groupA@"}
}, {
env: setEnv({NODE_ENV: 'groupb'}),
flags: {grep: "@groupB@"}
}, {
env: setEnv({NODE_ENV: 'groupc'}),
flags: {grep: "@groupC@"}
}]
};
var mocha = mochaStream(opts);
gulp.src('test/group/*-specs.js')
.pipe(mocha);
});

gulp.task('test', function() {
gulp.task('test', function () {
return runSequence(
'test-mocha',
'test-custom-mocha',
'test-live-output',
'test-live-output-with-prepend',
'test-live-output-with-file',
'test-with-file'
'test-with-file',
'test-mocha-opts-parallel'
);
});
Loading