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

Inquery: Would this project welcome a PR that adds in a programmatic API? #1953

Closed
chevcast opened this issue Oct 30, 2015 · 1 comment
Closed

Comments

@chevcast
Copy link

I'm using Mocha all over the place these days and I love it. However, I often find myself parallelizing test runs. For example, I often have to spin up the same test suite multiple times for use with Sauce Labs cloud testing on multiple platforms. The only way to do this currently is to spin up child processes and load up those processes with different environment variables, telling the test suite which platform and browser to fire up when talking to Sauce Labs.

Here's an example of this happening in a gulpfile:

gulp.task('selenium', (done) => {
  selenium.install((err) => {
    if (err) return done(err);
    selenium.start((err, child) => {
      if (err) return done(err);
      selenium.child = child;
      done();
    });
  });
});

var testDependencies = [];
if (yargs.argv.local) {
  testDependencies.push('selenium');
}
gulp.task('test', testDependencies, () => {
  var targets;
  if (yargs.argv.local) {
    targets = [
      'mac.chrome',
      'mac.firefox'
      //'mac.safari'
    ];
  } else {
    targets = [
      'windows.chrome',
      'windows.firefox',
      'windows.ie',
      'mac.chrome',
      'mac.firefox',
      'mac.safari',
      'linux.chrome',
      'linux.firefox'
    ];
  }

  function runMocha(target, done) {
    var env = Object.assign({ TARGET: target }, process.env);
    var args = ['--color', '--colors'];
    if (yargs.argv.local) {
      args.push('--local');
    }
    var mocha = spawn('mocha', args, { env });
    mocha.stdout
      .pipe(split())
      .pipe(through(function (text, enc, callback) {
        text = text.toString().replace('\r', '').trim();
        if (stripColorCodes(text).length > 0) {
          var padded = `${target.blue}:                              `.slice(0, 30);
          this.push(`${padded} ${text}${endOfLine}`);
        }
        callback();
      }))
      .pipe(process.stdout);
    mocha.on('close', done);
  }

  var jobs = targets.map(
    (target) => new Promise( (resolve) => runMocha(target, resolve))
  );

  return Promise.all(jobs).then(() => {
    if (yargs.argv.local) {
      selenium.child.kill();
    }
    console.log('ALL SUCCESSFUL');
  });
});

This configuration works great for running local selenium tests as well as cloud selenium tests on Sauce Labs. It's just cumbersome and far more low-level than I'd like. Simple things become complicated, such as formatting the test output and preserving colors. You'll note above that I have to pass in both the --color and --colors flags to the child processes to force mocha and selenium to preserve their colors; otherwise they think they are not running in a TTY-enabled terminal. Similarly I have to pipe the streamed output into a custom transform stream so I can format things appropriately. I'd still have to do this to a degree even with a programmatic mocha but it would be much simpler and far more readable. It took a lot of poking and prodding to finally arrive at a solution that worked well and printed clean readable output.

I'm writing so much code like this that I thought maybe it's time to crack open the Mocha source and start working on a programmatic API. The ability to drive mocha programmatically would be a huge help for these kinds of scenarios. Instead of spawning child processes to drive the CLI interface, I could just create mocha instances right inside of gulp and pass in options.

Before I dedicate time to this I first want to make sure it's something that would be welcomed by the project maintainers. What do you guys think? Does this just not exist because nobody has taken the time to do it, or are there other reasons to oppose such a change? I welcome the feedback :)

@boneskull
Copy link
Contributor

#1457

I'm happy to hear suggestions about how this would be implemented. I was going to do it myself, but I have had higher priorities. I'm also a little hesitant to develop it in a silo. So, if you'd like to collaborate, maybe that would help me get off my ass. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants