Allow tests to run in random order

This commit is contained in:
Marcio Junior
2015-09-26 11:25:33 -03:00
parent 375a6f9fda
commit 3f3fa484b2
12 changed files with 423 additions and 10 deletions

View File

@@ -20,6 +20,8 @@ getJasmineRequireObj().Env = function(j$) {
var currentlyExecutingSuites = [];
var currentDeclarationSuite = null;
var throwOnExpectationFailure = false;
var random = false;
var seed = null;
var currentSuite = function() {
return currentlyExecutingSuites[currentlyExecutingSuites.length - 1];
@@ -169,6 +171,21 @@ getJasmineRequireObj().Env = function(j$) {
return throwOnExpectationFailure;
};
this.randomizeTests = function(value) {
random = !!value;
};
this.randomTests = function() {
return random;
};
this.seed = function(value) {
if (value) {
seed = value;
}
return seed;
};
var queueRunnerFactory = function(options) {
options.catchException = catchException;
options.clearStack = options.clearStack || clearStack;
@@ -200,6 +217,12 @@ getJasmineRequireObj().Env = function(j$) {
runnablesToRun = [topSuite.id];
}
}
var order = new j$.Order({
random: random,
seed: seed
});
var processor = new j$.TreeProcessor({
tree: topSuite,
runnableIds: runnablesToRun,
@@ -215,6 +238,9 @@ getJasmineRequireObj().Env = function(j$) {
}
currentlyExecutingSuites.pop();
reporter.suiteDone(result);
},
orderChildren: function(node) {
return order.sort(node.children);
}
});
@@ -226,7 +252,11 @@ getJasmineRequireObj().Env = function(j$) {
totalSpecsDefined: totalSpecsDefined
});
processor.execute(reporter.jasmineDone);
processor.execute(function() {
reporter.jasmineDone({
order: order
});
});
};
this.addReporter = function(reporterToAdd) {

46
src/core/Order.js Normal file
View File

@@ -0,0 +1,46 @@
/*jshint bitwise: false*/
getJasmineRequireObj().Order = function() {
function Order(options) {
this.random = 'random' in options ? options.random : true;
var seed = this.seed = options.seed || generateSeed();
this.sort = this.random ? randomOrder : naturalOrder;
function naturalOrder(items) {
return items;
}
function randomOrder(items) {
var copy = items.slice();
copy.sort(function(a, b) {
return jenkinsHash(seed + a.id) - jenkinsHash(seed + b.id);
});
return copy;
}
function generateSeed() {
return String(Math.random()).slice(-5);
}
// Bob Jenkins One-at-a-Time Hash algorithm is a non-cryptographic hash function
// used to get a different output when the key changes slighly.
// We use your return to sort the children randomly in a consistent way when
// used in conjunction with a seed
function jenkinsHash(key) {
var hash, i;
for(hash = i = 0; i < key.length; ++i) {
hash += key.charCodeAt(i);
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
}
return Order;
};

View File

@@ -5,6 +5,7 @@ getJasmineRequireObj().TreeProcessor = function() {
queueRunnerFactory = attrs.queueRunnerFactory,
nodeStart = attrs.nodeStart || function() {},
nodeComplete = attrs.nodeComplete || function() {},
orderChildren = attrs.orderChildren || function(node) { return node.children; },
stats = { valid: true },
processed = false,
defaultMin = Infinity,
@@ -68,8 +69,10 @@ getJasmineRequireObj().TreeProcessor = function() {
} else {
var hasExecutableChild = false;
for (var i = 0; i < node.children.length; i++) {
var child = node.children[i];
var orderedChildren = orderChildren(node);
for (var i = 0; i < orderedChildren.length; i++) {
var child = orderedChildren[i];
processNode(child, parentEnabled);
@@ -86,7 +89,7 @@ getJasmineRequireObj().TreeProcessor = function() {
executable: hasExecutableChild
};
segmentChildren(node, stats[node.id], executableIndex);
segmentChildren(node, orderedChildren, stats[node.id], executableIndex);
if (!node.canBeReentered() && stats[node.id].segments.length > 1) {
stats = { valid: false };
@@ -102,11 +105,11 @@ getJasmineRequireObj().TreeProcessor = function() {
return executableIndex === undefined ? defaultMax : executableIndex;
}
function segmentChildren(node, nodeStats, executableIndex) {
function segmentChildren(node, orderedChildren, nodeStats, executableIndex) {
var currentSegment = { index: 0, owner: node, nodes: [], min: startingMin(executableIndex), max: startingMax(executableIndex) },
result = [currentSegment],
lastMax = defaultMax,
orderedChildSegments = orderChildSegments(node.children);
orderedChildSegments = orderChildSegments(orderedChildren);
function isSegmentBoundary(minIndex) {
return lastMax !== defaultMax && minIndex !== defaultMin && lastMax < minIndex - 1;

View File

@@ -50,6 +50,7 @@ var getJasmineRequireObj = (function (jasmineGlobal) {
j$.Timer = jRequire.Timer();
j$.TreeProcessor = jRequire.TreeProcessor();
j$.version = jRequire.version();
j$.Order = jRequire.Order();
j$.matchers = jRequire.requireMatchers(jRequire, j$);