Skip to content

Commit 80b342c

Browse files
MoLowruyadorno
authored andcommitted
test_runner: accept testOnly in run
PR-URL: #49753Fixes: #49733 Reviewed-By: Chemi Atlow <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Raz Luvaton <[email protected]>
1 parent 0ccd463 commit 80b342c

File tree

4 files changed

+43
-17
lines changed

4 files changed

+43
-17
lines changed

‎doc/api/test.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -906,6 +906,8 @@ changes:
906906
number. If a nullish value is provided, each process gets its own port,
907907
incremented from the primary's `process.debugPort`.
908908
**Default:**`undefined`.
909+
*`only`:{boolean} If truthy, the test context will only run tests that
910+
have the `only` option set
909911
*`setup`{Function} A function that accepts the `TestsStream` instance
910912
and can be used to setup listeners before any tests are run.
911913
**Default:**`undefined`.

‎lib/internal/test_runner/runner.js‎

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,17 @@ function filterExecArgv(arg, i, arr){
154154
!ArrayPrototypeSome(kFilterArgValues,(p)=>arg===p||(i>0&&arr[i-1]===p)||StringPrototypeStartsWith(arg,`${p}=`));
155155
}
156156

157-
functiongetRunArgs({path, inspectPort, testNamePatterns }){
157+
functiongetRunArgs(path,{inspectPort, testNamePatterns, only}){
158158
constargv=ArrayPrototypeFilter(process.execArgv,filterExecArgv);
159159
if(isUsingInspector()){
160160
ArrayPrototypePush(argv,`--inspect-port=${getInspectPort(inspectPort)}`);
161161
}
162-
if(testNamePatterns){
162+
if(testNamePatterns!=null){
163163
ArrayPrototypeForEach(testNamePatterns,(pattern)=>ArrayPrototypePush(argv,`--test-name-pattern=${pattern}`));
164164
}
165+
if(only===true){
166+
ArrayPrototypePush(argv,'--test-only');
167+
}
165168
ArrayPrototypePush(argv,path);
166169

167170
returnargv;
@@ -345,17 +348,17 @@ class FileTest extends Test{
345348
}
346349
}
347350

348-
functionrunTestFile(path,root,inspectPort,filesWatcher,testNamePatterns){
351+
functionrunTestFile(path,filesWatcher,opts){
349352
constwatchMode=filesWatcher!=null;
350-
constsubtest=root.createSubtest(FileTest,path,async(t)=>{
351-
constargs=getRunArgs({__proto__: null,path,inspectPort, testNamePatterns });
353+
constsubtest=opts.root.createSubtest(FileTest,path,async(t)=>{
354+
constargs=getRunArgs(path,opts);
352355
conststdio=['pipe','pipe','pipe'];
353356
constenv={__proto__: null, ...process.env,NODE_TEST_CONTEXT: 'child-v8'};
354357
if(watchMode){
355358
stdio.push('ipc');
356359
env.WATCH_REPORT_DEPENDENCIES='1';
357360
}
358-
if(root.harness.shouldColorizeTestFiles){
361+
if(opts.root.harness.shouldColorizeTestFiles){
359362
env.FORCE_COLOR='1';
360363
}
361364

@@ -402,7 +405,7 @@ function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns){
402405
filesWatcher.runningProcesses.delete(path);
403406
filesWatcher.runningSubtests.delete(path);
404407
if(filesWatcher.runningSubtests.size===0){
405-
root.reporter[kEmitMessage]('test:watch:drained');
408+
opts.root.reporter[kEmitMessage]('test:watch:drained');
406409
}
407410
}
408411

@@ -425,10 +428,10 @@ function runTestFile(path, root, inspectPort, filesWatcher, testNamePatterns){
425428
returnsubtest.start();
426429
}
427430

428-
functionwatchFiles(testFiles,root,inspectPort,signal,testNamePatterns){
431+
functionwatchFiles(testFiles,opts){
429432
construnningProcesses=newSafeMap();
430433
construnningSubtests=newSafeMap();
431-
constwatcher=newFilesWatcher({__proto__: null,debounce: 200,mode: 'filter', signal });
434+
constwatcher=newFilesWatcher({__proto__: null,debounce: 200,mode: 'filter',signal: opts.signal});
432435
constfilesWatcher={__proto__: null, watcher, runningProcesses, runningSubtests };
433436

434437
watcher.on('changed',({ owners })=>{
@@ -444,19 +447,19 @@ function watchFiles(testFiles, root, inspectPort, signal, testNamePatterns){
444447
}
445448
if(!runningSubtests.size){
446449
// Reset the topLevel counter
447-
root.harness.counters.topLevel=0;
450+
opts.root.harness.counters.topLevel=0;
448451
}
449452
awaitrunningSubtests.get(file);
450-
runningSubtests.set(file,runTestFile(file,root,inspectPort,filesWatcher,testNamePatterns));
453+
runningSubtests.set(file,runTestFile(file,filesWatcher,opts));
451454
},undefined,(error)=>{
452455
triggerUncaughtException(error,true/* fromPromise */);
453456
}));
454457
});
455-
if(signal){
458+
if(opts.signal){
456459
kResistStopPropagation??=require('internal/event_target').kResistStopPropagation;
457-
signal.addEventListener(
460+
opts.signal.addEventListener(
458461
'abort',
459-
()=>root.postRun(),
462+
()=>opts.root.postRun(),
460463
{__proto__: null,once: true,[kResistStopPropagation]: true},
461464
);
462465
}
@@ -469,14 +472,17 @@ function run(options){
469472
options=kEmptyObject;
470473
}
471474
let{ testNamePatterns, shard }=options;
472-
const{ concurrency, timeout, signal, files, inspectPort, watch, setup }=options;
475+
const{ concurrency, timeout, signal, files, inspectPort, watch, setup, only}=options;
473476

474477
if(files!=null){
475478
validateArray(files,'options.files');
476479
}
477480
if(watch!=null){
478481
validateBoolean(watch,'options.watch');
479482
}
483+
if(only!=null){
484+
validateBoolean(only,'options.only');
485+
}
480486
if(shard!=null){
481487
validateObject(shard,'options.shard');
482488
// Avoid re-evaluating the shard object in case it's a getter
@@ -522,14 +528,15 @@ function run(options){
522528

523529
letpostRun=()=>root.postRun();
524530
letfilesWatcher;
531+
constopts={__proto__: null, root, signal, inspectPort, testNamePatterns, only };
525532
if(watch){
526-
filesWatcher=watchFiles(testFiles,root,inspectPort,signal,testNamePatterns);
533+
filesWatcher=watchFiles(testFiles,opts);
527534
postRun=undefined;
528535
}
529536
construnFiles=()=>{
530537
root.harness.bootstrapComplete=true;
531538
returnSafePromiseAllSettledReturnVoid(testFiles,(path)=>{
532-
constsubtest=runTestFile(path,root,inspectPort,filesWatcher,testNamePatterns);
539+
constsubtest=runTestFile(path,filesWatcher,opts);
533540
filesWatcher?.runningSubtests.set(path,subtest);
534541
returnsubtest;
535542
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'use strict';
2+
consttest=require('node:test');
3+
4+
test('this should be skipped');
5+
test.only('this should be executed');

‎test/parallel/test-runner-run.mjs‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,18 @@ describe('require(\'node:test\').run',{concurrency: true }, () =>{
148148
assert.strictEqual(result[5],'ok 2 - this should be executed\n');
149149
});
150150

151+
it('should pass only to children',async()=>{
152+
constresult=awaitrun({
153+
files: [join(testFixtures,'test_only.js')],
154+
only: true
155+
})
156+
.compose(tap)
157+
.toArray();
158+
159+
assert.strictEqual(result[2],'ok 1 - this should be skipped # SKIP \'only\' option not set\n');
160+
assert.strictEqual(result[5],'ok 2 - this should be executed\n');
161+
});
162+
151163
it('should emit "test:watch:drained" event on watch mode',async()=>{
152164
constcontroller=newAbortController();
153165
awaitrun({

0 commit comments

Comments
(0)