test_runner: flatten TAP output when running using --test

PR-URL: https://github.com/nodejs/node/pull/46440
Fixes: https://github.com/nodejs/node/issues/45833
Refs: https://github.com/nodejs/node/issues/45833
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
This commit is contained in:
Moshe Atlow 2023-02-18 18:19:24 +02:00 committed by GitHub
parent 9e840deecc
commit 3354f89dcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 788 additions and 761 deletions

View File

@ -8,9 +8,11 @@ const {
ArrayPrototypeSlice,
ArrayPrototypeSome,
ArrayPrototypeSort,
FunctionPrototypeCall,
Number,
ObjectAssign,
ObjectKeys,
PromisePrototypeThen,
SafePromiseAll,
SafePromiseAllReturnVoid,
SafePromiseAllSettledReturnVoid,
SafeMap,
@ -35,7 +37,14 @@ const { validateArray, validateBoolean } = require('internal/validators');
const { getInspectPort, isUsingInspector, isInspectorMessage } = require('internal/util/inspector');
const { kEmptyObject } = require('internal/util');
const { createTestTree } = require('internal/test_runner/harness');
const { kSubtestsFailed, Test } = require('internal/test_runner/test');
const {
kAborted,
kCancelledByParent,
kSubtestsFailed,
kTestCodeFailure,
kTestTimeoutFailure,
Test,
} = require('internal/test_runner/test');
const { TapParser } = require('internal/test_runner/tap_parser');
const { YAMLToJs } = require('internal/test_runner/yaml_to_js');
const { TokenKind } = require('internal/test_runner/tap_lexer');
@ -55,6 +64,9 @@ const kFilterArgs = ['--test', '--experimental-test-coverage', '--watch'];
const kFilterArgValues = ['--test-reporter', '--test-reporter-destination'];
const kDiagnosticsFilterArgs = ['tests', 'pass', 'fail', 'cancelled', 'skipped', 'todo', 'duration_ms'];
const kCanceledTests = new SafeSet()
.add(kCancelledByParent).add(kAborted).add(kTestTimeoutFailure);
// TODO(cjihrig): Replace this with recursive readdir once it lands.
function processPath(path, testFiles, options) {
const stats = statSync(path);
@ -133,6 +145,11 @@ function getRunArgs({ path, inspectPort }) {
class FileTest extends Test {
#buffer = [];
#counters = { __proto__: null, all: 0, failed: 0, passed: 0, cancelled: 0, skipped: 0, todo: 0, totalFailed: 0 };
failedSubtests = false;
#skipReporting() {
return this.#counters.all > 0 && (!this.error || this.error.failureType === kSubtestsFailed);
}
#checkNestedComment({ comment }) {
const firstSpaceIndex = StringPrototypeIndexOf(comment, ' ');
if (firstSpaceIndex === -1) return false;
@ -141,8 +158,6 @@ class FileTest extends Test {
ArrayPrototypeIncludes(kDiagnosticsFilterArgs, StringPrototypeSlice(comment, 0, firstSpaceIndex));
}
#handleReportItem({ kind, node, comments, nesting = 0 }) {
nesting += 1;
if (comments) {
ArrayPrototypeForEach(comments, (comment) => this.reporter.diagnostic(nesting, this.name, comment));
}
@ -153,6 +168,9 @@ class FileTest extends Test {
break;
case TokenKind.TAP_PLAN:
if (nesting === 0 && this.#skipReporting()) {
break;
}
this.reporter.plan(nesting, this.name, node.end - node.start + 1);
break;
@ -160,10 +178,10 @@ class FileTest extends Test {
this.reporter.start(nesting, this.name, node.name);
break;
case TokenKind.TAP_TEST_POINT:
// eslint-disable-next-line no-case-declarations
case TokenKind.TAP_TEST_POINT: {
const { todo, skip, pass } = node.status;
// eslint-disable-next-line no-case-declarations
let directive;
if (skip) {
@ -174,29 +192,22 @@ class FileTest extends Test {
directive = kEmptyObject;
}
if (pass) {
this.reporter.ok(
nesting,
this.name,
node.id,
node.description,
YAMLToJs(node.diagnostics),
directive,
);
} else {
this.reporter.fail(
nesting,
this.name,
node.id,
node.description,
YAMLToJs(node.diagnostics),
directive,
);
const diagnostics = YAMLToJs(node.diagnostics);
const cancelled = kCanceledTests.has(diagnostics.error?.failureType);
const testNumber = nesting === 0 ? (Number(node.id) + this.testNumber - 1) : node.id;
const method = pass ? 'ok' : 'fail';
this.reporter[method](nesting, this.name, testNumber, node.description, diagnostics, directive);
if (nesting === 0) {
FunctionPrototypeCall(super.countSubtest,
{ finished: true, skipped: skip, isTodo: todo, passed: pass, cancelled },
this.#counters);
this.failedSubtests ||= !pass;
}
break;
}
case TokenKind.COMMENT:
if (nesting === 1 && this.#checkNestedComment(node)) {
if (nesting === 0 && this.#checkNestedComment(node)) {
// Ignore file top level diagnostics
break;
}
@ -216,10 +227,24 @@ class FileTest extends Test {
this.reportStarted();
this.#handleReportItem(ast);
}
countSubtest(counters) {
if (this.#counters.all === 0) {
return super.countSubtest(counters);
}
ArrayPrototypeForEach(ObjectKeys(counters), (key) => {
counters[key] += this.#counters[key];
});
}
reportStarted() {}
report() {
this.reportStarted();
const skipReporting = this.#skipReporting();
if (!skipReporting) {
super.reportStarted();
}
ArrayPrototypeForEach(this.#buffer, (ast) => this.#handleReportItem(ast));
super.report();
if (!skipReporting) {
super.report();
}
}
}
@ -274,16 +299,14 @@ function runTestFile(path, root, inspectPort, filesWatcher) {
subtest.addToReport(ast);
});
const { 0: { 0: code, 1: signal } } = await SafePromiseAll([
once(child, 'exit', { signal: t.signal }),
child.stdout.toArray({ signal: t.signal }),
]);
const { 0: code, 1: signal } = await once(child, 'exit', { signal: t.signal });
runningProcesses.delete(path);
runningSubtests.delete(path);
if (code !== 0 || signal !== null) {
if (!err) {
err = ObjectAssign(new ERR_TEST_FAILURE('test failed', kSubtestsFailed), {
const failureType = subtest.failedSubtests ? kSubtestsFailed : kTestCodeFailure;
err = ObjectAssign(new ERR_TEST_FAILURE('test failed', failureType), {
__proto__: null,
exitCode: code,
signal: signal,

View File

@ -57,6 +57,7 @@ const { availableParallelism } = require('os');
const { bigint: hrtime } = process.hrtime;
const kCallbackAndPromisePresent = 'callbackAndPromisePresent';
const kCancelledByParent = 'cancelledByParent';
const kAborted = 'testAborted';
const kParentAlreadyFinished = 'parentAlreadyFinished';
const kSubtestsFailed = 'subtestsFailed';
const kTestCodeFailure = 'testCodeFailure';
@ -390,10 +391,12 @@ class Test extends AsyncResource {
}
#abortHandler = () => {
this.cancel(this.#outerSignal?.reason || new AbortError('The test was aborted'));
const error = this.#outerSignal?.reason || new AbortError('The test was aborted');
error.failureType = kAborted;
this.#cancel(error);
};
cancel(error) {
#cancel(error) {
if (this.endTime !== null) {
return;
}
@ -470,7 +473,7 @@ class Test extends AsyncResource {
return true;
}
if (this.#outerSignal?.aborted) {
this.cancel(this.#outerSignal.reason || new AbortError('The test was aborted'));
this.#abortHandler();
return true;
}
}
@ -563,7 +566,7 @@ class Test extends AsyncResource {
try { await afterEach(); } catch { /* test is already failing, let's the error */ }
if (isTestFailureError(err)) {
if (err.failureType === kTestTimeoutFailure) {
this.cancel(err);
this.#cancel(err);
} else {
this.fail(err);
}
@ -577,9 +580,31 @@ class Test extends AsyncResource {
this.postRun();
}
postRun(pendingSubtestsError) {
const counters = { __proto__: null, failed: 0, passed: 0, cancelled: 0, skipped: 0, todo: 0, totalFailed: 0 };
countSubtest(counters) {
// Check SKIP and TODO tests first, as those should not be counted as
// failures.
if (this.skipped) {
counters.skipped++;
} else if (this.isTodo) {
counters.todo++;
} else if (this.cancelled) {
counters.cancelled++;
} else if (!this.passed) {
counters.failed++;
} else {
counters.passed++;
}
if (!this.passed) {
counters.totalFailed++;
}
counters.all++;
}
postRun(pendingSubtestsError) {
const counters = {
__proto__: null, all: 0, failed: 0, passed: 0, cancelled: 0, skipped: 0, todo: 0, totalFailed: 0,
};
// If the test was failed before it even started, then the end time will
// be earlier than the start time. Correct that here.
if (this.endTime < this.startTime) {
@ -594,27 +619,10 @@ class Test extends AsyncResource {
const subtest = this.subtests[i];
if (!subtest.finished) {
subtest.cancel(pendingSubtestsError);
subtest.#cancel(pendingSubtestsError);
subtest.postRun(pendingSubtestsError);
}
// Check SKIP and TODO tests first, as those should not be counted as
// failures.
if (subtest.skipped) {
counters.skipped++;
} else if (subtest.isTodo) {
counters.todo++;
} else if (subtest.cancelled) {
counters.cancelled++;
} else if (!subtest.passed) {
counters.failed++;
} else {
counters.passed++;
}
if (!subtest.passed) {
counters.totalFailed++;
}
subtest.countSubtest(counters);
}
if ((this.passed || this.parent === null) && counters.totalFailed > 0) {
@ -634,13 +642,13 @@ class Test extends AsyncResource {
this.parent.processPendingSubtests();
} else if (!this.reported) {
this.reported = true;
this.reporter.plan(this.nesting, kFilename, this.subtests.length);
this.reporter.plan(this.nesting, kFilename, counters.all);
for (let i = 0; i < this.diagnostics.length; i++) {
this.reporter.diagnostic(this.nesting, kFilename, this.diagnostics[i]);
}
this.reporter.diagnostic(this.nesting, kFilename, `tests ${this.subtests.length}`);
this.reporter.diagnostic(this.nesting, kFilename, `tests ${counters.all}`);
this.reporter.diagnostic(this.nesting, kFilename, `pass ${counters.passed}`);
this.reporter.diagnostic(this.nesting, kFilename, `fail ${counters.failed}`);
this.reporter.diagnostic(this.nesting, kFilename, `cancelled ${counters.cancelled}`);
@ -825,6 +833,8 @@ module.exports = {
kCancelledByParent,
kSubtestsFailed,
kTestCodeFailure,
kTestTimeoutFailure,
kAborted,
kUnwrapErrors,
Suite,
Test,

View File

@ -40,6 +40,7 @@ TAP version 13
not ok 7 - not ok 3
---
duration_ms: *
failureType: 'testAborted'
error: 'This operation was aborted'
code: 20
stack: |-
@ -58,6 +59,7 @@ TAP version 13
not ok 8 - not ok 4
---
duration_ms: *
failureType: 'testAborted'
error: 'This operation was aborted'
code: 20
stack: |-
@ -76,6 +78,7 @@ TAP version 13
not ok 9 - not ok 5
---
duration_ms: *
failureType: 'testAborted'
error: 'This operation was aborted'
code: 20
stack: |-
@ -94,6 +97,7 @@ TAP version 13
not ok 1 - promise timeout signal
---
duration_ms: *
failureType: 'testAborted'
error: 'The operation was aborted due to timeout'
code: 23
stack: |-
@ -106,6 +110,7 @@ not ok 1 - promise timeout signal
not ok 2 - promise abort signal
---
duration_ms: *
failureType: 'testAborted'
error: 'This operation was aborted'
code: 20
stack: |-
@ -160,6 +165,7 @@ not ok 2 - promise abort signal
not ok 7 - not ok 3
---
duration_ms: *
failureType: 'testAborted'
error: 'This operation was aborted'
code: 20
stack: |-
@ -178,6 +184,7 @@ not ok 2 - promise abort signal
not ok 8 - not ok 4
---
duration_ms: *
failureType: 'testAborted'
error: 'This operation was aborted'
code: 20
stack: |-
@ -196,6 +203,7 @@ not ok 2 - promise abort signal
not ok 9 - not ok 5
---
duration_ms: *
failureType: 'testAborted'
error: 'This operation was aborted'
code: 20
stack: |-
@ -214,6 +222,7 @@ not ok 2 - promise abort signal
not ok 3 - callback timeout signal
---
duration_ms: *
failureType: 'testAborted'
error: 'The operation was aborted due to timeout'
code: 23
stack: |-
@ -226,6 +235,7 @@ not ok 3 - callback timeout signal
not ok 4 - callback abort signal
---
duration_ms: *
failureType: 'testAborted'
error: 'This operation was aborted'
code: 20
stack: |-

View File

@ -64,6 +64,7 @@ TAP version 13
not ok 1 - describe timeout signal
---
duration_ms: *
failureType: 'testAborted'
error: 'The operation was aborted due to timeout'
code: 23
stack: |-
@ -76,6 +77,7 @@ not ok 1 - describe timeout signal
not ok 2 - describe abort signal
---
duration_ms: *
failureType: 'testAborted'
error: 'This operation was aborted'
code: 20
stack: |-

File diff suppressed because it is too large Load Diff

View File

@ -28,11 +28,10 @@ const testFixtures = fixtures.path('test-runner');
assert.strictEqual(child.signal, null);
assert.strictEqual(child.stderr.toString(), '');
const stdout = child.stdout.toString();
assert.match(stdout, /ok 1 - .+index\.test\.js/);
assert.match(stdout, /not ok 2 - .+random\.test\.mjs/);
assert.match(stdout, /not ok 1 - this should fail/);
assert.match(stdout, /ok 1 - this should pass/);
assert.match(stdout, /not ok 2 - this should fail/);
assert.match(stdout, /ok 3 - .+subdir.+subdir_test\.js/);
assert.match(stdout, /ok 4 - .+random\.cjs/);
assert.match(stdout, /ok 4 - this should pass/);
}
{
@ -41,11 +40,10 @@ const testFixtures = fixtures.path('test-runner');
const child = spawnSync(process.execPath, args);
const stdout = child.stdout.toString();
assert.match(stdout, /ok 1 - .+index\.test\.js/);
assert.match(stdout, /not ok 2 - .+random\.test\.mjs/);
assert.match(stdout, /not ok 1 - this should fail/);
assert.match(stdout, /ok 1 - this should pass/);
assert.match(stdout, /not ok 2 - this should fail/);
assert.match(stdout, /ok 3 - .+subdir.+subdir_test\.js/);
assert.match(stdout, /ok 4 - .+random\.cjs/);
assert.match(stdout, /ok 4 - this should pass/);
assert.strictEqual(child.status, 1);
assert.strictEqual(child.signal, null);
assert.strictEqual(child.stderr.toString(), '');
@ -61,10 +59,10 @@ const testFixtures = fixtures.path('test-runner');
assert.strictEqual(child.stderr.toString(), '');
const stdout = child.stdout.toString();
assert.match(stdout, /not ok 1 - .+index\.js/);
assert.match(stdout, /ok 2 - .+index\.test\.js/);
assert.match(stdout, /not ok 3 - .+random\.test\.mjs/);
assert.match(stdout, /not ok 1 - this should fail/);
assert.match(stdout, /ok 2 - this should pass/);
assert.match(stdout, /not ok 3 - this should fail/);
assert.match(stdout, /ok 4 - .+subdir.+subdir_test\.js/);
assert.match(stdout, /ok 5 - this should pass/);
}
{
@ -89,11 +87,10 @@ const testFixtures = fixtures.path('test-runner');
assert.strictEqual(child.signal, null);
assert.strictEqual(child.stderr.toString(), '');
const stdout = child.stdout.toString();
assert.match(stdout, /ok 1 - .+index\.test\.js/);
assert.match(stdout, /not ok 2 - .+random\.test\.mjs/);
assert.match(stdout, /not ok 1 - this should fail/);
assert.match(stdout, /ok 1 - this should pass/);
assert.match(stdout, /not ok 2 - this should fail/);
assert.match(stdout, /ok 3 - .+subdir.+subdir_test\.js/);
assert.match(stdout, /ok 4 - .+random\.cjs/);
assert.match(stdout, /ok 4 - this should pass/);
}
{
@ -131,42 +128,36 @@ const testFixtures = fixtures.path('test-runner');
assert.strictEqual(child.signal, null);
assert.strictEqual(child.stderr.toString(), '');
const stdout = child.stdout.toString();
assert.match(stdout, /# Subtest: .+index\.test\.js/);
assert.match(stdout, / {4}# Subtest: this should pass/);
assert.match(stdout, / {4}ok 1 - this should pass/);
assert.match(stdout, / {6}---/);
assert.match(stdout, / {6}duration_ms: .*/);
assert.match(stdout, / {6}\.\.\./);
assert.match(stdout, / {4}1\.\.1/);
assert.match(stdout, /ok 1 - .+index\.test\.js/);
assert.match(stdout, /# Subtest: this should pass/);
assert.match(stdout, /ok 1 - this should pass/);
assert.match(stdout, / {2}---/);
assert.match(stdout, / {2}duration_ms: .*/);
assert.match(stdout, / {2}\.\.\./);
assert.match(stdout, /# Subtest: .+invalid-tap\.js/);
assert.match(stdout, / {4}# invalid tap output/);
assert.match(stdout, /# invalid tap output/);
assert.match(stdout, /ok 2 - .+invalid-tap\.js/);
assert.match(stdout, /# Subtest: .+nested\.js/);
assert.match(stdout, / {4}# Subtest: level 0a/);
assert.match(stdout, / {8}# Subtest: level 1a/);
assert.match(stdout, / {8}ok 1 - level 1a/);
assert.match(stdout, / {8}# Subtest: level 1b/);
assert.match(stdout, / {8}not ok 2 - level 1b/);
assert.match(stdout, / {10}code: 'ERR_TEST_FAILURE'/);
assert.match(stdout, / {10}stack: |-'/);
assert.match(stdout, / {12}TestContext\.<anonymous> .*/);
assert.match(stdout, / {8}# Subtest: level 1c/);
assert.match(stdout, / {8}ok 3 - level 1c # SKIP aaa/);
assert.match(stdout, / {8}# Subtest: level 1d/);
assert.match(stdout, / {8}ok 4 - level 1d/);
assert.match(stdout, / {4}not ok 1 - level 0a/);
assert.match(stdout, / {6}error: '1 subtest failed'/);
assert.match(stdout, / {4}# Subtest: level 0b/);
assert.match(stdout, / {4}not ok 2 - level 0b/);
assert.match(stdout, / {6}error: 'level 0b error'/);
assert.match(stdout, /not ok 3 - .+nested\.js/);
assert.match(stdout, /# tests 3/);
assert.match(stdout, /# Subtest: level 0a/);
assert.match(stdout, / {4}# Subtest: level 1a/);
assert.match(stdout, / {4}ok 1 - level 1a/);
assert.match(stdout, / {4}# Subtest: level 1b/);
assert.match(stdout, / {4}not ok 2 - level 1b/);
assert.match(stdout, / {6}code: 'ERR_TEST_FAILURE'/);
assert.match(stdout, / {6}stack: |-'/);
assert.match(stdout, / {8}TestContext\.<anonymous> .*/);
assert.match(stdout, / {4}# Subtest: level 1c/);
assert.match(stdout, / {4}ok 3 - level 1c # SKIP aaa/);
assert.match(stdout, / {4}# Subtest: level 1d/);
assert.match(stdout, / {4}ok 4 - level 1d/);
assert.match(stdout, /not ok 3 - level 0a/);
assert.match(stdout, / {2}error: '1 subtest failed'/);
assert.match(stdout, /# Subtest: level 0b/);
assert.match(stdout, /not ok 4 - level 0b/);
assert.match(stdout, / {2}error: 'level 0b error'/);
assert.match(stdout, /# tests 4/);
assert.match(stdout, /# pass 2/);
assert.match(stdout, /# fail 1/);
assert.match(stdout, /# fail 2/);
}
{
@ -181,16 +172,15 @@ const testFixtures = fixtures.path('test-runner');
assert.strictEqual(child.signal, null);
assert.strictEqual(child.stderr.toString(), '');
const stdout = child.stdout.toString();
assert.match(stdout, /# Subtest: .+user-logs\.js/);
assert.match(stdout, / {4}# stderr 1/);
assert.match(stdout, / {4}# stderr 2/);
assert.match(stdout, / {4}# stdout 3/);
assert.match(stdout, / {4}# stderr 6/);
assert.match(stdout, / {4}# not ok 1 - fake test/);
assert.match(stdout, / {4}# stderr 5/);
assert.match(stdout, / {4}# stdout 4/);
assert.match(stdout, / {4}# Subtest: a test/);
assert.match(stdout, / {4}ok 1 - a test/);
assert.match(stdout, /# stderr 1/);
assert.match(stdout, /# stderr 2/);
assert.match(stdout, /# stdout 3/);
assert.match(stdout, /# stderr 6/);
assert.match(stdout, /# not ok 1 - fake test/);
assert.match(stdout, /# stderr 5/);
assert.match(stdout, /# stdout 4/);
assert.match(stdout, /# Subtest: a test/);
assert.match(stdout, /ok 1 - a test/);
assert.match(stdout, /# tests 1/);
assert.match(stdout, /# pass 1/);
}

View File

@ -10,8 +10,9 @@ const { spawnSync } = require('child_process');
fixtures.path('test-runner', 'extraneous_set_immediate_async.mjs'),
]);
const stdout = child.stdout.toString();
assert.match(stdout, /^# pass 0$/m);
assert.match(stdout, /^# fail 1$/m);
assert.match(stdout, /^# Warning: Test "extraneous async activity test" generated asynchronous activity after the test ended/m);
assert.match(stdout, /^# pass 1/m);
assert.match(stdout, /^# fail 0$/m);
assert.match(stdout, /^# cancelled 0$/m);
assert.strictEqual(child.status, 1);
assert.strictEqual(child.signal, null);
@ -23,8 +24,9 @@ const { spawnSync } = require('child_process');
fixtures.path('test-runner', 'extraneous_set_timeout_async.mjs'),
]);
const stdout = child.stdout.toString();
assert.match(stdout, /^# pass 0$/m);
assert.match(stdout, /^# fail 1$/m);
assert.match(stdout, /^# Warning: Test "extraneous async activity test" generated asynchronous activity after the test ended/m);
assert.match(stdout, /^# pass 1$/m);
assert.match(stdout, /^# fail 0$/m);
assert.match(stdout, /^# cancelled 0$/m);
assert.strictEqual(child.status, 1);
assert.strictEqual(child.signal, null);

View File

@ -26,7 +26,7 @@ describe('node:test reporters', { concurrency: true }, () => {
it('should default destination to stdout when passing a single reporter', async () => {
const child = spawnSync(process.execPath, ['--test', '--test-reporter', 'dot', testFile]);
assert.strictEqual(child.stderr.toString(), '');
assert.strictEqual(child.stdout.toString(), '.XX.X\n');
assert.strictEqual(child.stdout.toString(), '.XX.\n');
});
it('should throw when passing reporters without a destination', async () => {
@ -45,13 +45,13 @@ describe('node:test reporters', { concurrency: true }, () => {
const child = spawnSync(process.execPath,
['--test', '--test-reporter', 'dot', '--test-reporter-destination', 'stdout', testFile]);
assert.strictEqual(child.stderr.toString(), '');
assert.strictEqual(child.stdout.toString(), '.XX.X\n');
assert.strictEqual(child.stdout.toString(), '.XX.\n');
});
it('should support stderr as a destination', async () => {
const child = spawnSync(process.execPath,
['--test', '--test-reporter', 'dot', '--test-reporter-destination', 'stderr', testFile]);
assert.strictEqual(child.stderr.toString(), '.XX.X\n');
assert.strictEqual(child.stderr.toString(), '.XX.\n');
assert.strictEqual(child.stdout.toString(), '');
});
@ -61,7 +61,7 @@ describe('node:test reporters', { concurrency: true }, () => {
['--test', '--test-reporter', 'dot', '--test-reporter-destination', file, testFile]);
assert.strictEqual(child.stderr.toString(), '');
assert.strictEqual(child.stdout.toString(), '');
assert.strictEqual(fs.readFileSync(file, 'utf8'), '.XX.X\n');
assert.strictEqual(fs.readFileSync(file, 'utf8'), '.XX.\n');
});
it('should support multiple reporters', async () => {
@ -75,7 +75,7 @@ describe('node:test reporters', { concurrency: true }, () => {
testFile]);
assert.match(child.stdout.toString(), /TAP version 13/);
assert.match(child.stdout.toString(), /# duration_ms/);
assert.strictEqual(fs.readFileSync(file, 'utf8'), '.XX.X\n');
assert.strictEqual(fs.readFileSync(file, 'utf8'), '.XX.\n');
const file2Contents = fs.readFileSync(file2, 'utf8');
assert.match(file2Contents, /▶ nested/);
assert.match(file2Contents, /✔ ok/);
@ -90,7 +90,7 @@ describe('node:test reporters', { concurrency: true }, () => {
testFile]);
assert.strictEqual(child.stderr.toString(), '');
const stdout = child.stdout.toString();
assert.match(stdout, /{"test:start":5,"test:pass":2,"test:fail":3,"test:plan":3,"test:diagnostic":\d+}$/);
assert.match(stdout, /{"test:start":4,"test:pass":2,"test:fail":2,"test:plan":2,"test:diagnostic":\d+}$/);
assert.strictEqual(stdout.slice(0, filename.length + 2), `${filename} {`);
});
});
@ -102,7 +102,7 @@ describe('node:test reporters', { concurrency: true }, () => {
assert.strictEqual(child.stderr.toString(), '');
assert.match(
child.stdout.toString(),
/^package: reporter-cjs{"test:start":5,"test:pass":2,"test:fail":3,"test:plan":3,"test:diagnostic":\d+}$/,
/^package: reporter-cjs{"test:start":4,"test:pass":2,"test:fail":2,"test:plan":2,"test:diagnostic":\d+}$/,
);
});
@ -113,7 +113,7 @@ describe('node:test reporters', { concurrency: true }, () => {
assert.strictEqual(child.stderr.toString(), '');
assert.match(
child.stdout.toString(),
/^package: reporter-esm{"test:start":5,"test:pass":2,"test:fail":3,"test:plan":3,"test:diagnostic":\d+}$/,
/^package: reporter-esm{"test:start":4,"test:pass":2,"test:fail":2,"test:plan":2,"test:diagnostic":\d+}$/,
);
});
});

View File

@ -27,7 +27,7 @@ describe('require(\'node:test\').run', { concurrency: true }, () => {
it('should succeed with a file', async () => {
const stream = run({ files: [join(testFixtures, 'test/random.cjs')] });
stream.on('test:fail', common.mustNotCall());
stream.on('test:pass', common.mustCall(2));
stream.on('test:pass', common.mustCall(1));
// eslint-disable-next-line no-unused-vars
for await (const _ of stream);
});
@ -35,7 +35,7 @@ describe('require(\'node:test\').run', { concurrency: true }, () => {
it('should run same file twice', async () => {
const stream = run({ files: [join(testFixtures, 'test/random.cjs'), join(testFixtures, 'test/random.cjs')] });
stream.on('test:fail', common.mustNotCall());
stream.on('test:pass', common.mustCall(4));
stream.on('test:pass', common.mustCall(2));
// eslint-disable-next-line no-unused-vars
for await (const _ of stream);
});