Skip to content

Commit

Permalink
Add randomization support
Browse files Browse the repository at this point in the history
Fixes #902.
  • Loading branch information
TimothyGu authored and boneskull committed Sep 19, 2016
1 parent 9e7f5f2 commit 2fe3fe4
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 9 deletions.
8 changes: 8 additions & 0 deletions bin/_mocha
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ program
.option('-O, --reporter-options <k=v,k2=v2,...>', 'reporter-specific options')
.option('-R, --reporter <name>', 'specify the reporter to use', 'spec')
.option('-S, --sort', 'sort test files')
.option('-a, --randomize <mode>[:seed]', "randomize tests")
.option('-b, --bail', 'bail after first test failure')
.option('-d, --debug', "enable node's debugger, synonym for node --debug")
.option('-g, --grep <pattern>', 'only run tests matching <pattern>')
Expand Down Expand Up @@ -275,6 +276,13 @@ if (program.fgrep) {
mocha.fgrep(program.fgrep);
}

// --randomize

if (program.randomize) {
var matches = program.randomize.split(':');
mocha.randomize(matches[0], matches[1]);
}

// --invert

if (program.invert) {
Expand Down
20 changes: 20 additions & 0 deletions lib/interfaces/bdd.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ module.exports = function(suite) {
});
};

/**
* Do not randomize.
*/
context.describe.noRandom = function func(title, fn) {
var suite = context.describe(title, fn);
suite.enableRandomize(false);
return suite;
};
// these three are disabled anyway, so don't actually implement noRandom
context.describe.noRandom.skip =
context.describe.skip.noRandom =
context.xdescribe.noRandom =
context.describe.skip;

/**
* Exclusive suite.
*/
Expand All @@ -69,6 +83,12 @@ module.exports = function(suite) {
fn: fn
});
};
context.describe.only.noRandom =
context.describe.noRandom.only = function(title, fn){
var suite = context.describe.noRandom(title, fn);
mocha.grep(suite.fullTitle());
return suite;
};

/**
* Describe a specification or test-case
Expand Down
22 changes: 22 additions & 0 deletions lib/interfaces/qunit.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,28 @@ module.exports = function(suite) {
});
};

/**
* Do not randomize.
*/
context.suite.noRandom = function(title) {
var suite = common.suite.create({
title: title,
file: file,
});
suite.enableRandomize(false);
return suite;
};

context.suite.only.noRandom =
context.suite.noRandom.only = function(title) {
var suite = common.suite.only({
title: title,
file: file,
});
suite.enableRandomize(false);
return suite;
};

/**
* Exclusive Suite.
*/
Expand Down
15 changes: 15 additions & 0 deletions lib/interfaces/tdd.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,16 @@ module.exports = function(suite) {
});
};

/**
* Do not randomize.
*/
context.suite.noRandom = function(title, fn) {
var suite = context.suite(title, fn);
suite.enableRandomize(false);
return suite;
};
context.suite.noRandom.skip = context.suite.skip;

/**
* Exclusive test-case.
*/
Expand All @@ -74,6 +84,11 @@ module.exports = function(suite) {
fn: fn
});
};
context.suite.only.noRandom =
context.suite.noRandom.only = function(title, fn){
var suite = context.suite.noRandom(title, fn);
mocha.grep(suite.fullTitle());
};

/**
* Describe a specification or test-case with the given `title` and
Expand Down
33 changes: 31 additions & 2 deletions lib/mocha.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ function image(name) {
* - `ignoreLeaks` ignore global leaks
* - `fullTrace` display the full stack-trace on failing
* - `grep` string or regexp to filter tests with
* - `randomMode` mode for randomization of tests
* - `randomSeed` seed for randomization of tests
*
* @param {Object} options
* @api public
Expand Down Expand Up @@ -288,19 +290,42 @@ Mocha.prototype.invert = function() {
};

/**
* Ignore global leaks.
* Apply randomization to the tests
*
* @param {Boolean} ignore
* @param {String} mode
* @param seed
* @return {Mocha}
* @api public
* @param {boolean} ignore
* @return {Mocha}
*/
Mocha.prototype.ignoreLeaks = function(ignore) {
if (mode !== 'tests' /* && mode !== 'suites' && mode !== 'both' */) {
throw new Error('unrecognized randomization mode "' + mode + '"');
}
this.options.randomizeMode = mode;
this.options.ignoreLeaks = Boolean(ignore);
return this;
};

/**
* Apply randomization to the tests
*
* @param {String} mode
* @param seed
* @return {Mocha}
* @api public
*/

Mocha.prototype.randomize = function(mode, seed){
if (mode !== 'tests' /* && mode !== 'suites' && mode !== 'both' */) {
throw new Error('unrecognized randomization mode "' + mode + '"');
}
this.options.randomizeMode = mode;
this.options.randomizeSeed = seed != null ? seed : Math.random();
return this;
};

/**
* Enable global leak checking.
*
Expand Down Expand Up @@ -506,6 +531,10 @@ Mocha.prototype.run = function(fn) {
if (options.useColors !== undefined) {
exports.reporters.Base.useColors = options.useColors;
}
if (options.randomizeMode !== undefined) {
runner.randomize(options.randomizeMode, options.randomizeSeed);
}

exports.reporters.Base.inlineDiffs = options.useInlineDiffs;

function done(failures) {
Expand Down
20 changes: 20 additions & 0 deletions lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,25 @@ Runner.prototype.checkGlobals = function(test) {
}
};

/**
* Randomize tests in a suite.
*
* @param seed
* @return {Runner} for chaining
* @api public
*/

Runner.prototype.randomize = function(mode, seed){
debug('randomize mode: "' + mode + '"; seed: ' + seed);
if (mode !== 'tests') return this;
this._randomize = function(suite){
debug('randomize: ', suite.title, suite._enableRandomize);
if (!suite._enableRandomize) return suite.tests;
return randomize(suite.tests, seed);
}
return this;
};

/**
* Fail the given `test`.
*
Expand Down Expand Up @@ -448,6 +467,7 @@ Runner.prototype.runTest = function(fn) {
Runner.prototype.runTests = function(suite, fn) {
var self = this;
var tests = suite.tests.slice();
if (self._randomize) self._randomize(self.suite);
var test;

function hookErr(_, errSuite, after) {
Expand Down
20 changes: 20 additions & 0 deletions lib/suite.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ function Suite(title, parentContext) {
this._slow = 75;
this._bail = false;
this._retries = -1;
this._enableRandomize = false;
this._onlyTests = [];
this._onlySuites = [];
this.delayed = false;
Expand All @@ -86,6 +87,7 @@ Suite.prototype.clone = function() {
suite.enableTimeouts(this.enableTimeouts());
suite.slow(this.slow());
suite.bail(this.bail());
suite.enableRandomize(this.enableRandomize());
return suite;
};

Expand Down Expand Up @@ -187,6 +189,24 @@ Suite.prototype.isPending = function() {
return this.pending || (this.parent && this.parent.isPending());
};

/**
* Set randomization `enabled`.
*
* Do NOT use `this.enableRandomize()` in your test; use `describe.noRandom`
* instead.
*
* @param {Boolean} enabled
* @return {Suite|Boolean} self or enabled
* @api private
*/

Suite.prototype.enableRandomize = function(enabled){
if (arguments.length === 0) return this._enableRandomize;
debug('enableRandomize %s', enabled);
this._enableRandomize = enabled;
return this;
};

/**
* Run `fn(test[, done])` before running tests.
*
Expand Down
4 changes: 2 additions & 2 deletions test/hook-async.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
describe('async', function(){
describe.noRandom('async', function(){
var calls = [];

before(function(){
Expand Down Expand Up @@ -43,7 +43,7 @@ describe('async', function(){
calls.push('parent after' );
})

describe('hooks', function(){
describe.noRandom('hooks', function(){
before(function(){
calls.push('before all');
});
Expand Down
6 changes: 3 additions & 3 deletions test/hook-sync-nested.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
describe('serial', function(){
describe('nested', function(){
describe.noRandom('serial', function(){
describe.noRandom('nested', function(){
var calls = [];

beforeEach(function(){
Expand Down Expand Up @@ -34,7 +34,7 @@ describe('serial', function(){
, 'parent before test bar']);
})

describe('hooks', function(){
describe.noRandom('hooks', function(){
beforeEach(function(){
calls.push('before');
if (this.currentTest) {
Expand Down
4 changes: 2 additions & 2 deletions test/hook-sync.spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
describe('serial', function(){
describe.noRandom('serial', function(){
var calls = [];

beforeEach(function(){
Expand All @@ -9,7 +9,7 @@ describe('serial', function(){
calls.push('parent after');
})

describe('hooks', function(){
describe.noRandom('hooks', function(){
beforeEach(function(){
calls.push('before');
if (this.currentTest) {
Expand Down

0 comments on commit 2fe3fe4

Please sign in to comment.