@@ -49,13 +49,14 @@ const populateGroups = numberOfWorkers => {
4949 return groups
5050}
5151
52- const createWorker = workerObject => {
52+ const createWorker = ( workerObject , isPoolMode = false ) => {
5353 const worker = new Worker ( pathToWorker , {
5454 workerData : {
5555 options : simplifyObject ( workerObject . options ) ,
5656 tests : workerObject . tests ,
5757 testRoot : workerObject . testRoot ,
5858 workerIndex : workerObject . workerIndex + 1 ,
59+ poolMode : isPoolMode ,
5960 } ,
6061 } )
6162 worker . on ( 'error' , err => output . error ( `Worker Error: ${ err . stack } ` ) )
@@ -236,6 +237,9 @@ class Workers extends EventEmitter {
236237 this . closedWorkers = 0
237238 this . workers = [ ]
238239 this . testGroups = [ ]
240+ this . testPool = [ ]
241+ this . isPoolMode = config . by === 'pool'
242+ this . activeWorkers = new Map ( )
239243
240244 createOutputDir ( config . testConfig )
241245 if ( numberOfWorkers ) this . _initWorkers ( numberOfWorkers , config )
@@ -255,6 +259,7 @@ class Workers extends EventEmitter {
255259 *
256260 * - `suite`
257261 * - `test`
262+ * - `pool`
258263 * - function(numberOfWorkers)
259264 *
260265 * This method can be overridden for a better split.
@@ -270,7 +275,11 @@ class Workers extends EventEmitter {
270275 this . testGroups . push ( convertToMochaTests ( testGroup ) )
271276 }
272277 } else if ( typeof numberOfWorkers === 'number' && numberOfWorkers > 0 ) {
273- this . testGroups = config . by === 'suite' ? this . createGroupsOfSuites ( numberOfWorkers ) : this . createGroupsOfTests ( numberOfWorkers )
278+ if ( config . by === 'pool' ) {
279+ this . createTestPool ( numberOfWorkers )
280+ } else {
281+ this . testGroups = config . by === 'suite' ? this . createGroupsOfSuites ( numberOfWorkers ) : this . createGroupsOfTests ( numberOfWorkers )
282+ }
274283 }
275284 }
276285
@@ -311,7 +320,29 @@ class Workers extends EventEmitter {
311320 /**
312321 * @param {Number } numberOfWorkers
313322 */
314- createGroupsOfSuites ( numberOfWorkers ) {
323+ createTestPool ( numberOfWorkers ) {
324+ const files = this . codecept . testFiles
325+ const mocha = Container . mocha ( )
326+ mocha . files = files
327+ mocha . loadFiles ( )
328+
329+ mocha . suite . eachTest ( test => {
330+ if ( test ) {
331+ this . testPool . push ( test . uid )
332+ }
333+ } )
334+
335+ // For pool mode, create empty groups for each worker
336+ this . testGroups = populateGroups ( numberOfWorkers )
337+ }
338+
339+ /**
340+ * Gets the next test from the pool
341+ * @returns {String|null } test uid or null if no tests available
342+ */
343+ getNextTest ( ) {
344+ return this . testPool . shift ( ) || null
345+ }
315346 const files = this . codecept . testFiles
316347 const groups = populateGroups ( numberOfWorkers )
317348
@@ -352,7 +383,7 @@ class Workers extends EventEmitter {
352383 process . env . RUNS_WITH_WORKERS = 'true'
353384 recorder . add ( 'starting workers' , ( ) => {
354385 for ( const worker of this . workers ) {
355- const workerThread = createWorker ( worker )
386+ const workerThread = createWorker ( worker , this . isPoolMode )
356387 this . _listenWorkerEvents ( workerThread )
357388 }
358389 } )
@@ -376,9 +407,45 @@ class Workers extends EventEmitter {
376407 }
377408
378409 _listenWorkerEvents ( worker ) {
410+ // Track worker thread for pool mode
411+ if ( this . isPoolMode ) {
412+ this . activeWorkers . set ( worker , { available : true , workerIndex : null } )
413+ }
414+
379415 worker . on ( 'message' , message => {
380416 output . process ( message . workerIndex )
381417
418+ // Handle test requests for pool mode
419+ if ( message . type === 'REQUEST_TEST' ) {
420+ if ( this . isPoolMode ) {
421+ const nextTest = this . getNextTest ( )
422+ if ( nextTest ) {
423+ worker . postMessage ( { type : 'TEST_ASSIGNED' , test : nextTest } )
424+ const workerInfo = this . activeWorkers . get ( worker )
425+ if ( workerInfo ) {
426+ workerInfo . available = false
427+ workerInfo . workerIndex = message . workerIndex
428+ }
429+ } else {
430+ worker . postMessage ( { type : 'NO_MORE_TESTS' } )
431+ const workerInfo = this . activeWorkers . get ( worker )
432+ if ( workerInfo ) {
433+ workerInfo . available = true
434+ }
435+ }
436+ }
437+ return
438+ }
439+
440+ // Handle test completion for pool mode
441+ if ( message . type === 'TEST_COMPLETED' && this . isPoolMode ) {
442+ const workerInfo = this . activeWorkers . get ( worker )
443+ if ( workerInfo ) {
444+ workerInfo . available = true
445+ }
446+ return
447+ }
448+
382449 // deal with events that are not test cycle related
383450 if ( ! message . event ) {
384451 return this . emit ( 'message' , message )
0 commit comments