Skip to content

Commit

Permalink
Core: Revamp processing order to one test at a time
Browse files Browse the repository at this point in the history
  • Loading branch information
Trent Willis committed Mar 25, 2017
1 parent 9c51391 commit e75efe8
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 88 deletions.
105 changes: 53 additions & 52 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,88 +25,89 @@ export const globalSuite = new SuiteReport();
// it since each module has a suiteReport associated with it.
config.currentModule.suiteReport = globalSuite;

const moduleStack = [];
var globalStartCalled = false;
var runStarted = false;

export const internalState = {
autorun: false
};

// Figure out if we're running the tests from a server or not
QUnit.isLocal = !( defined.document && window.location.protocol !== "file:" );

// Expose the current QUnit version
QUnit.version = "@VERSION";

function createModule( name, testEnvironment ) {
const parentModule = moduleStack.length ? moduleStack.slice( -1 )[ 0 ] : null;
const moduleName = parentModule !== null ? [ parentModule.name, name ].join( " > " ) : name;
const parentSuite = parentModule ? parentModule.suiteReport : globalSuite;

const module = {
name: moduleName,
parentModule: parentModule,
tests: [],
moduleId: generateHash( moduleName ),
testsRun: 0,
childModules: [],
suiteReport: new SuiteReport( name, parentSuite )
};

const env = {};
if ( parentModule ) {
parentModule.childModules.push( module );
extend( env, parentModule.testEnvironment );
}
extend( env, testEnvironment );
module.testEnvironment = env;

config.modules.push( module );
return module;
}

extend( QUnit, {
on,

// Call on start of module test to prepend name to all tests
module: function( name, testEnvironment, executeNow ) {
var module, moduleFns;
var currentModule = config.currentModule;

if ( arguments.length === 2 ) {
if ( objectType( testEnvironment ) === "function" ) {
executeNow = testEnvironment;
testEnvironment = undefined;
}
}

module = createModule();
let module = createModule( name, testEnvironment );

// Move any hooks to a 'hooks' object
if ( module.testEnvironment ) {
module.hooks = {
before: module.testEnvironment.before,
beforeEach: module.testEnvironment.beforeEach,
afterEach: module.testEnvironment.afterEach,
after: module.testEnvironment.after
};

delete module.testEnvironment.before;
delete module.testEnvironment.beforeEach;
delete module.testEnvironment.afterEach;
delete module.testEnvironment.after;
}

moduleFns = {
const moduleFns = {
before: setHook( module, "before" ),
beforeEach: setHook( module, "beforeEach" ),
afterEach: setHook( module, "afterEach" ),
after: setHook( module, "after" )
};

const currentModule = config.currentModule;
if ( objectType( executeNow ) === "function" ) {
config.moduleStack.push( module );
setCurrentModule( module );
moduleStack.push( module );
config.currentModule = module;
executeNow.call( module.testEnvironment, moduleFns );
config.moduleStack.pop();
moduleStack.pop();
module = module.parentModule || currentModule;
}

setCurrentModule( module );

function createModule() {
var parentModule = config.moduleStack.length ?
config.moduleStack.slice( -1 )[ 0 ] : null;
var moduleName = parentModule !== null ?
[ parentModule.name, name ].join( " > " ) : name;
var parentSuite = parentModule ? parentModule.suiteReport : globalSuite;

var module = {
name: moduleName,
parentModule: parentModule,
tests: [],
moduleId: generateHash( moduleName ),
testsRun: 0,
childModules: [],
suiteReport: new SuiteReport( name, parentSuite )
};

var env = {};
if ( parentModule ) {
parentModule.childModules.push( module );
extend( env, parentModule.testEnvironment );
delete env.beforeEach;
delete env.afterEach;
}
extend( env, testEnvironment );
module.testEnvironment = env;

config.modules.push( module );
return module;
}

function setCurrentModule( module ) {
config.currentModule = module;
}

config.currentModule = module;
},

test: test,
Expand Down Expand Up @@ -245,12 +246,12 @@ export function begin() {
}

function setHook( module, hookName ) {
if ( module.testEnvironment === undefined ) {
module.testEnvironment = {};
if ( !module.hooks ) {
module.hooks = {};
}

return function( callback ) {
module.testEnvironment[ hookName ] = callback;
module.hooks[ hookName ] = callback;
};
}

Expand Down
3 changes: 0 additions & 3 deletions src/core/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ const config = {
// Set of all modules.
modules: [],

// Stack of nested modules
moduleStack: [],

// The first unnamed module
currentModule: {
name: "",
Expand Down
42 changes: 25 additions & 17 deletions src/core/processing-queue.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
} from "./logging";

import {
internalState,
globalSuite
} from "../core";
import {
Expand Down Expand Up @@ -41,6 +40,10 @@ function advance() {
config.current.usedAsync = false;
}

if ( priorityCount > 0 ) {
priorityCount--;
}

config.queue.shift()();
} else {
setTimeout( advance, 13 );
Expand All @@ -55,38 +58,39 @@ function advance() {
}
}

/**
* Adds a function to the ProcessingQueue for execution.
* @param {Function|Array} callback
* @param {Boolean} priority
* @param {String} seed
*/
function addToQueue( callback, priority, seed ) {
function addToQueueImmediate( callback ) {
if ( objectType( callback ) === "array" ) {
while ( callback.length ) {
addToQueue( callback.shift() );
addToQueueImmediate( callback.pop() );
}

return;
}

if ( priority ) {
config.queue.unshift( callback );
priorityCount++;
}

/**
* Adds a function to the ProcessingQueue for execution.
* @param {Function|Array} callback
* @param {Boolean} priority
* @param {String} seed
*/
function addToQueue( callback, prioritize, seed ) {
if ( prioritize ) {
config.queue.splice( priorityCount++, 0, callback );
} else if ( seed ) {
if ( !unitSampler ) {
unitSampler = unitSamplerGenerator( seed );
}

// Insert into a random position after all priority items
// Insert into a random position after all prioritized items
const index = Math.floor( unitSampler() * ( config.queue.length - priorityCount + 1 ) );
config.queue.splice( priorityCount + index, 0, callback );
} else {
config.queue.push( callback );
}

if ( internalState.autorun && !config.blocking ) {
advance();
}
}

/**
Expand Down Expand Up @@ -118,7 +122,7 @@ function unitSamplerGenerator( seed ) {
function done() {
const storage = config.storage;

internalState.autorun = true;
ProcessingQueue.finished = true;

const runtime = now() - config.started;
const passed = config.stats.all - config.stats.bad;
Expand All @@ -143,7 +147,11 @@ function done() {
}
}

export default {
const ProcessingQueue = {
finished: false,
add: addToQueue,
addImmediate: addToQueueImmediate,
advance
};

export default ProcessingQueue;
29 changes: 13 additions & 16 deletions src/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,6 @@ Test.prototype = {

config.current = this;

if ( module.testEnvironment ) {
delete module.testEnvironment.before;
delete module.testEnvironment.beforeEach;
delete module.testEnvironment.afterEach;
delete module.testEnvironment.after;
}
this.testEnvironment = extend( {}, module.testEnvironment );

this.started = now();
Expand Down Expand Up @@ -203,9 +197,8 @@ Test.prototype = {
if ( module.parentModule ) {
processHooks( test, module.parentModule );
}
if ( module.testEnvironment &&
objectType( module.testEnvironment[ handler ] ) === "function" ) {
hooks.push( test.queueHook( module.testEnvironment[ handler ], handler, module ) );
if ( module.hooks && objectType( module.hooks[ handler ] ) === "function" ) {
hooks.push( test.queueHook( module.hooks[ handler ], handler, module ) );
}
}

Expand Down Expand Up @@ -303,9 +296,8 @@ Test.prototype = {
}
},

queue: function() {
var priority, previousFailCount,
test = this;
queue() {
const test = this;

if ( !this.valid() ) {
return;
Expand All @@ -314,7 +306,7 @@ Test.prototype = {
function run() {

// Each of these can by async
ProcessingQueue.add( [
ProcessingQueue.addImmediate( [
function() {
test.before();
},
Expand Down Expand Up @@ -344,15 +336,20 @@ Test.prototype = {
] );
}

previousFailCount = config.storage &&
const previousFailCount = config.storage &&
+config.storage.getItem( "qunit-test-" + this.module.name + "-" + this.testName );

// Prioritize previously failed tests, detected from storage
priority = config.reorder && previousFailCount;
const prioritize = config.reorder && !!previousFailCount;

this.previousFailure = !!previousFailCount;

return ProcessingQueue.add( run, priority, config.seed );
ProcessingQueue.add( run, prioritize, config.seed );

// If the queue has already finished, we manually process the new test
if ( ProcessingQueue.finished ) {
ProcessingQueue.advance();
}
},

pushResult: function( resultInfo ) {
Expand Down

0 comments on commit e75efe8

Please sign in to comment.