docs: 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();
  
  		if ( testEnvironment && ( testEnvironment.setup || testEnvironment.teardown ) ) {
  			console.warn(
  				"Module's `setup` and `teardown` are not hooks anymore on QUnit 2.0, use " +
  				"`beforeEach` and `afterEach` instead\n" +
  				"Details in our upgrade guide at https://qunitjs.com/upgrade-guide-2.x/"
  			);
  		}
  
  		moduleFns = {
  			before: setHook( module, "before" ),
  			beforeEach: setHook( module, "beforeEach" ),
  			afterEach: setHook( module, "afterEach" ),
  			after: setHook( module, "after" )
  		};
  
  		if ( objectType( executeNow ) === "function" ) {
  			config.moduleStack.push( module );
  			setCurrentModule( module );
  			executeNow.call( module.testEnvironment, moduleFns );
  			config.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 module = {
  				name: moduleName,
  				parentModule: parentModule,
  				tests: [],
  				moduleId: generateHash( moduleName ),
  				testsRun: 0
  			};
  
  			var env = {};
  			if ( parentModule ) {
  				parentModule.childModule = 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;
  		}
  
  	}