Skip to content

Commit 602e6bb

Browse files
committed
test_runner: flatten TAP output when running using --test
1 parent 3abd559 commit 602e6bb

File tree

7 files changed

+677
-690
lines changed

7 files changed

+677
-690
lines changed

lib/internal/test_runner/runner.js

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ const {
88
ArrayPrototypeSlice,
99
ArrayPrototypeSome,
1010
ArrayPrototypeSort,
11+
Number,
1112
ObjectAssign,
1213
PromisePrototypeThen,
13-
SafePromiseAll,
1414
SafePromiseAllReturnVoid,
1515
SafePromiseAllSettledReturnVoid,
1616
SafeMap,
@@ -33,7 +33,7 @@ const { validateArray, validateBoolean } = require('internal/validators');
3333
const { getInspectPort, isUsingInspector, isInspectorMessage } = require('internal/util/inspector');
3434
const { kEmptyObject } = require('internal/util');
3535
const { createTestTree } = require('internal/test_runner/harness');
36-
const { kSubtestsFailed, Test } = require('internal/test_runner/test');
36+
const { kSubtestsFailed, kTestCodeFailure, kCancelledByParent, Test } = require('internal/test_runner/test');
3737
const { TapParser } = require('internal/test_runner/tap_parser');
3838
const { YAMLToJs } = require('internal/test_runner/yaml_to_js');
3939
const { TokenKind } = require('internal/test_runner/tap_lexer');
@@ -130,27 +130,32 @@ function getRunArgs({ path, inspectPort }) {
130130

131131
class FileTest extends Test {
132132
#buffer = [];
133+
#hasSubtests = false;
134+
get skipReporting() {
135+
return this.#hasSubtests && (!this.error || this.error.failureType === kSubtestsFailed);
136+
}
133137
#handleReportItem({ kind, node, nesting = 0 }) {
134-
nesting += 1;
135-
136138
switch (kind) {
137139
case TokenKind.TAP_VERSION:
138140
// TODO(manekinekko): handle TAP version coming from the parser.
139141
// this.reporter.version(node.version);
140142
break;
141143

142144
case TokenKind.TAP_PLAN:
145+
if (nesting === 0 && this.skipReporting) {
146+
break;
147+
}
143148
this.reporter.plan(nesting, this.name, node.end - node.start + 1);
144149
break;
145150

146151
case TokenKind.TAP_SUBTEST_POINT:
147152
this.reporter.start(nesting, this.name, node.name);
148153
break;
149154

150-
case TokenKind.TAP_TEST_POINT:
151-
// eslint-disable-next-line no-case-declarations
155+
case TokenKind.TAP_TEST_POINT: {
156+
152157
const { todo, skip, pass } = node.status;
153-
// eslint-disable-next-line no-case-declarations
158+
154159
let directive;
155160

156161
if (skip) {
@@ -161,29 +166,20 @@ class FileTest extends Test {
161166
directive = kEmptyObject;
162167
}
163168

164-
if (pass) {
165-
this.reporter.ok(
166-
nesting,
167-
this.name,
168-
node.id,
169-
node.description,
170-
YAMLToJs(node.diagnostics),
171-
directive
172-
);
173-
} else {
174-
this.reporter.fail(
175-
nesting,
176-
this.name,
177-
node.id,
178-
node.description,
179-
YAMLToJs(node.diagnostics),
180-
directive
181-
);
169+
this.#hasSubtests = true;
170+
const diagnostics = YAMLToJs(node.diagnostics);
171+
const cancelled = diagnostics.error?.failureType === kCancelledByParent;
172+
const testNumber = nesting === 0 ? (Number(node.id) + this.testNumber - 1) : node.id;
173+
const method = pass ? 'ok' : 'fail';
174+
this.reporter[method](nesting, this.name, testNumber, node.description, diagnostics, directive);
175+
if (nesting === 0) {
176+
this.parent.countSubtest({ finished: true, skipped: skip, isTodo: todo, passed: pass, cancelled });
177+
this.countSubtest({ finished: true, skipped: skip, isTodo: todo, passed: pass, cancelled });
182178
}
183179
break;
184180

185-
case TokenKind.COMMENT:
186-
if (nesting === 1) {
181+
} case TokenKind.COMMENT:
182+
if (nesting === 0) {
187183
// Ignore file top level diagnostics
188184
break;
189185
}
@@ -203,10 +199,15 @@ class FileTest extends Test {
203199
this.reportStarted();
204200
this.#handleReportItem(ast);
205201
}
202+
reportStarted() {}
206203
report() {
207-
this.reportStarted();
204+
if (!this.skipReporting) {
205+
super.reportStarted();
206+
}
208207
ArrayPrototypeForEach(this.#buffer, (ast) => this.#handleReportItem(ast));
209-
super.report();
208+
if (!this.skipReporting) {
209+
super.report();
210+
}
210211
}
211212
}
212213

@@ -261,16 +262,14 @@ function runTestFile(path, root, inspectPort, filesWatcher) {
261262
subtest.addToReport(ast);
262263
});
263264

264-
const { 0: { 0: code, 1: signal } } = await SafePromiseAll([
265-
once(child, 'exit', { signal: t.signal }),
266-
child.stdout.toArray({ signal: t.signal }),
267-
]);
265+
const { 0: code, 1: signal } = await once(child, 'exit', { signal: t.signal });
268266

269267
runningProcesses.delete(path);
270268
runningSubtests.delete(path);
271269
if (code !== 0 || signal !== null) {
272270
if (!err) {
273-
err = ObjectAssign(new ERR_TEST_FAILURE('test failed', kSubtestsFailed), {
271+
const failureType = subtest.completedCounters.totalFailed > 0 ? kSubtestsFailed : kTestCodeFailure;
272+
err = ObjectAssign(new ERR_TEST_FAILURE('test failed', failureType), {
274273
__proto__: null,
275274
exitCode: code,
276275
signal: signal,

lib/internal/test_runner/test.js

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ class Test extends AsyncResource {
286286
beforeEach: [],
287287
afterEach: [],
288288
};
289+
this.completedCounters = {
290+
all: 0, failed: 0, passed: 0, cancelled: 0, skipped: 0, todo: 0, totalFailed: 0
291+
};
289292
this.waitingOn = 0;
290293
this.finished = false;
291294
}
@@ -577,9 +580,32 @@ class Test extends AsyncResource {
577580
this.postRun();
578581
}
579582

580-
postRun(pendingSubtestsError) {
581-
const counters = { __proto__: null, failed: 0, passed: 0, cancelled: 0, skipped: 0, todo: 0, totalFailed: 0 };
583+
countSubtest(subtest) {
584+
if (subtest.skipReporting || subtest.counted) {
585+
return;
586+
}
587+
subtest.counted = true;
588+
// Check SKIP and TODO tests first, as those should not be counted as
589+
// failures.
590+
if (subtest.skipped) {
591+
this.completedCounters.skipped++;
592+
} else if (subtest.isTodo) {
593+
this.completedCounters.todo++;
594+
} else if (subtest.cancelled) {
595+
this.completedCounters.cancelled++;
596+
} else if (!subtest.passed) {
597+
this.completedCounters.failed++;
598+
} else {
599+
this.completedCounters.passed++;
600+
}
601+
602+
if (!subtest.passed) {
603+
this.completedCounters.totalFailed++;
604+
}
605+
this.completedCounters.all++;
606+
}
582607

608+
postRun(pendingSubtestsError) {
583609
// If the test was failed before it even started, then the end time will
584610
// be earlier than the start time. Correct that here.
585611
if (this.endTime < this.startTime) {
@@ -592,34 +618,15 @@ class Test extends AsyncResource {
592618
this.pendingSubtests = [];
593619
for (let i = 0; i < this.subtests.length; i++) {
594620
const subtest = this.subtests[i];
595-
596621
if (!subtest.finished) {
597622
subtest.cancel(pendingSubtestsError);
598623
subtest.postRun(pendingSubtestsError);
599624
}
600-
601-
// Check SKIP and TODO tests first, as those should not be counted as
602-
// failures.
603-
if (subtest.skipped) {
604-
counters.skipped++;
605-
} else if (subtest.isTodo) {
606-
counters.todo++;
607-
} else if (subtest.cancelled) {
608-
counters.cancelled++;
609-
} else if (!subtest.passed) {
610-
counters.failed++;
611-
} else {
612-
counters.passed++;
613-
}
614-
615-
if (!subtest.passed) {
616-
counters.totalFailed++;
617-
}
618625
}
619626

620-
if ((this.passed || this.parent === null) && counters.totalFailed > 0) {
621-
const subtestString = `subtest${counters.totalFailed > 1 ? 's' : ''}`;
622-
const msg = `${counters.totalFailed} ${subtestString} failed`;
627+
if ((this.passed || this.parent === null) && this.completedCounters.totalFailed > 0) {
628+
const subtestString = `subtest${this.completedCounters.totalFailed > 1 ? 's' : ''}`;
629+
const msg = `${this.completedCounters.totalFailed} ${subtestString} failed`;
623630

624631
this.fail(new ERR_TEST_FAILURE(msg, kSubtestsFailed));
625632
}
@@ -632,20 +639,21 @@ class Test extends AsyncResource {
632639
this.parent.addReadySubtest(this);
633640
this.parent.processReadySubtestRange(false);
634641
this.parent.processPendingSubtests();
642+
this.parent.countSubtest(this);
635643
} else if (!this.reported) {
636644
this.reported = true;
637-
this.reporter.plan(this.nesting, kFilename, this.subtests.length);
645+
this.reporter.plan(this.nesting, kFilename, this.completedCounters.all);
638646

639647
for (let i = 0; i < this.diagnostics.length; i++) {
640648
this.reporter.diagnostic(this.nesting, kFilename, this.diagnostics[i]);
641649
}
642650

643-
this.reporter.diagnostic(this.nesting, kFilename, `tests ${this.subtests.length}`);
644-
this.reporter.diagnostic(this.nesting, kFilename, `pass ${counters.passed}`);
645-
this.reporter.diagnostic(this.nesting, kFilename, `fail ${counters.failed}`);
646-
this.reporter.diagnostic(this.nesting, kFilename, `cancelled ${counters.cancelled}`);
647-
this.reporter.diagnostic(this.nesting, kFilename, `skipped ${counters.skipped}`);
648-
this.reporter.diagnostic(this.nesting, kFilename, `todo ${counters.todo}`);
651+
this.reporter.diagnostic(this.nesting, kFilename, `tests ${this.completedCounters.all}`);
652+
this.reporter.diagnostic(this.nesting, kFilename, `pass ${this.completedCounters.passed}`);
653+
this.reporter.diagnostic(this.nesting, kFilename, `fail ${this.completedCounters.failed}`);
654+
this.reporter.diagnostic(this.nesting, kFilename, `cancelled ${this.completedCounters.cancelled}`);
655+
this.reporter.diagnostic(this.nesting, kFilename, `skipped ${this.completedCounters.skipped}`);
656+
this.reporter.diagnostic(this.nesting, kFilename, `todo ${this.completedCounters.todo}`);
649657
this.reporter.diagnostic(this.nesting, kFilename, `duration_ms ${this.#duration()}`);
650658

651659
if (this.coverage) {

0 commit comments

Comments
 (0)