ChevCast
ChevCast

Reputation: 59213

How can I pass custom data to my mocha tests?

We are using sauce labs to do cross-platform/cross-browser testing.

You can find my test suite in this gist (to save room in this question): https://gist.github.com/chevex/397a5a18a1a386897b41

The problem is that the only way I could figure out how to pass custom data to the test suite is via an environment variable. Because of this, when my gulp task tries to run the test suite against multiple targets in parallel, they all end up running against the same target since the loop is done iterating and process.env.SAUCE_TARGET is set to the final value before the first suite even runs.

var gulp = require('gulp');
var gulpMocha = require('gulp-mocha');
var mergeStream = require('merge-stream');
gulp.task('sauce-tests', function () {
  var targets = ['chrome', 'firefox', 'internet explorer'];
  var streams = targets.map(function (target) {
    process.env.SAUCE_TARGET = target;
    return gulp.src('./test/sauce-tests.js', {read:false})
      .pipe(gulpMocha({ reporter: 'spec' });
  });
  return mergeStream.apply(null, streams);
});

The closure provided by forEach doesn't help because it's setting an essentially global value (process.env.SAUCE_TARGET) on each iteration.

Is there a better way to pass the SAUCE_TARGET to my test suite so that I can run multiple test suites in parallel with different target values?

I can get it working if I run all the tests synchronously but that takes far longer than I want it to. The only thing preventing parallelism is the fact that I can't pass encapsulated values to my mocha suite.

Upvotes: 2

Views: 756

Answers (2)

just-boris
just-boris

Reputation: 9756

You can run tests in several browsers in parallel using child_process module.

var exec = require('child_process').exec;

function runMochaTests(browser) {
   return new Promise(function(resolve, reject) {
       var env = {SAUCE_TARGET: browser};
       exec('./node_modules/.bin/mocha --reporter spec', {env: env}, function(err) {
          if(err !== null) {
              return reject(err);
          }
          return resolve();
       });
   });
}

It creates child process with test. Current browser will be availabe as process.env.SAUCE_TARGET.

Then you can use this function in gulp task to run tests in different browsers.

gulp.task('tests', function() {
    return Promise.all(['chrome', 'firefox', 'internet explorer'].map(function(browser) {
        return runMochaTests(browsers);
    }));
});

Here is used Promises because gulp can accept them as a task result and will wait until tests will be finished in all browsers.

Also you can add here some syntax sugar like denodeify to make work with exec a bit shorter.

Upvotes: 2

Lim H.
Lim H.

Reputation: 10050

You can try setting it in between pipes, specifically with the flush function:

  var through = require('through2');

  var setTarget = function (target) {
      return through.obj(
          function (chunk, enc, cb) { cb(null, chunk) },
          function (cb) { // flush function 
              process.env.SAUCE_TARGET = target;
              cb();
          }
      );
  }
  var streams = targets.map(function (target) {
    return gulp.src('./test/sauce-tests.js', {read:false})
      .pipe(setTarget(target))
      .pipe(gulpMocha({ reporter: 'spec', globals: [target] });
  });

Upvotes: 0

Related Questions