Skip to content

Commit

Permalink
test_runner: report file in test runner events
Browse files Browse the repository at this point in the history
PR-URL: #46030
Backport-PR-URL: #46839
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
  • Loading branch information
MoLow authored and juanarbol committed Mar 5, 2023
1 parent 403df21 commit 79f4b42
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 28 deletions.
10 changes: 10 additions & 0 deletions doc/api/test.md
Expand Up @@ -1204,6 +1204,8 @@ object, streaming a series of events representing the execution of the tests.
### Event: `'test:diagnostic'`

* `data` {Object}
* `file` {string|undefined} The path of the test file,
undefined if test is not ran through a file.
* `message` {string} The diagnostic message.
* `nesting` {number} The nesting level of the test.

Expand All @@ -1215,6 +1217,8 @@ Emitted when [`context.diagnostic`][] is called.
* `details` {Object} Additional execution metadata.
* `duration` {number} The duration of the test in milliseconds.
* `error` {Error} The error thrown by the test.
* `file` {string|undefined} The path of the test file,
undefined if test is not ran through a file.
* `name` {string} The test name.
* `nesting` {number} The nesting level of the test.
* `testNumber` {number} The ordinal number of the test.
Expand All @@ -1228,6 +1232,8 @@ Emitted when a test fails.
* `data` {Object}
* `details` {Object} Additional execution metadata.
* `duration` {number} The duration of the test in milliseconds.
* `file` {string|undefined} The path of the test file,
undefined if test is not ran through a file.
* `name` {string} The test name.
* `nesting` {number} The nesting level of the test.
* `testNumber` {number} The ordinal number of the test.
Expand All @@ -1239,6 +1245,8 @@ Emitted when a test passes.
### Event: `'test:plan'`

* `data` {Object}
* `file` {string|undefined} The path of the test file,
undefined if test is not ran through a file.
* `nesting` {number} The nesting level of the test.
* `count` {number} The number of subtests that have ran.

Expand All @@ -1247,6 +1255,8 @@ Emitted when all subtests have completed for a given test.
### Event: `'test:start'`

* `data` {Object}
* `file` {string|undefined} The path of the test file,
undefined if test is not ran through a file.
* `name` {string} The test name.
* `nesting` {number} The nesting level of the test.

Expand Down
10 changes: 6 additions & 4 deletions lib/internal/test_runner/runner.js
Expand Up @@ -139,11 +139,11 @@ class FileTest extends Test {
break;

case TokenKind.TAP_PLAN:
this.reporter.plan(nesting, node.end - node.start + 1);
this.reporter.plan(nesting, this.name, node.end - node.start + 1);
break;

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

case TokenKind.TAP_TEST_POINT:
Expand All @@ -163,6 +163,7 @@ class FileTest extends Test {
if (pass) {
this.reporter.ok(
nesting,
this.name,
node.id,
node.description,
YAMLToJs(node.diagnostics),
Expand All @@ -171,6 +172,7 @@ class FileTest extends Test {
} else {
this.reporter.fail(
nesting,
this.name,
node.id,
node.description,
YAMLToJs(node.diagnostics),
Expand All @@ -184,11 +186,11 @@ class FileTest extends Test {
// Ignore file top level diagnostics
break;
}
this.reporter.diagnostic(nesting, node.comment);
this.reporter.diagnostic(nesting, this.name, node.comment);
break;

case TokenKind.UNKNOWN:
this.reporter.diagnostic(nesting, node.value);
this.reporter.diagnostic(nesting, this.name, node.value);
break;
}
}
Expand Down
29 changes: 15 additions & 14 deletions lib/internal/test_runner/test.js
Expand Up @@ -74,6 +74,7 @@ const testNamePatterns = testNamePatternFlag?.length > 0 ?
(re) => convertStringToRegExp(re, '--test-name-pattern')
) : null;
const kShouldAbort = Symbol('kShouldAbort');
const kFilename = process.argv?.[1];
const kHookNames = ObjectSeal(['before', 'after', 'beforeEach', 'afterEach']);
const kUnwrapErrors = new SafeSet()
.add(kTestCodeFailure).add(kHookFailure)
Expand Down Expand Up @@ -632,19 +633,19 @@ class Test extends AsyncResource {
this.parent.processPendingSubtests();
} else if (!this.reported) {
this.reported = true;
this.reporter.plan(this.nesting, this.subtests.length);
this.reporter.plan(this.nesting, kFilename, this.subtests.length);

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

this.reporter.diagnostic(this.nesting, `tests ${this.subtests.length}`);
this.reporter.diagnostic(this.nesting, `pass ${counters.passed}`);
this.reporter.diagnostic(this.nesting, `fail ${counters.failed}`);
this.reporter.diagnostic(this.nesting, `cancelled ${counters.cancelled}`);
this.reporter.diagnostic(this.nesting, `skipped ${counters.skipped}`);
this.reporter.diagnostic(this.nesting, `todo ${counters.todo}`);
this.reporter.diagnostic(this.nesting, `duration_ms ${this.#duration()}`);
this.reporter.diagnostic(this.nesting, kFilename, `tests ${this.subtests.length}`);
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}`);
this.reporter.diagnostic(this.nesting, kFilename, `skipped ${counters.skipped}`);
this.reporter.diagnostic(this.nesting, kFilename, `todo ${counters.todo}`);
this.reporter.diagnostic(this.nesting, kFilename, `duration_ms ${this.#duration()}`);
this.reporter.push(null);
}
}
Expand Down Expand Up @@ -680,7 +681,7 @@ class Test extends AsyncResource {

report() {
if (this.subtests.length > 0) {
this.reporter.plan(this.subtests[0].nesting, this.subtests.length);
this.reporter.plan(this.subtests[0].nesting, kFilename, this.subtests.length);
} else {
this.reportStarted();
}
Expand All @@ -694,14 +695,14 @@ class Test extends AsyncResource {
}

if (this.passed) {
this.reporter.ok(this.nesting, this.testNumber, this.name, details, directive);
this.reporter.ok(this.nesting, kFilename, this.testNumber, this.name, details, directive);
} else {
details.error = this.error;
this.reporter.fail(this.nesting, this.testNumber, this.name, details, directive);
this.reporter.fail(this.nesting, kFilename, this.testNumber, this.name, details, directive);
}

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

Expand All @@ -711,7 +712,7 @@ class Test extends AsyncResource {
}
this.#reportedSubtest = true;
this.parent.reportStarted();
this.reporter.start(this.nesting, this.name);
this.reporter.start(this.nesting, kFilename, this.name);
}
}

Expand Down
20 changes: 10 additions & 10 deletions lib/internal/test_runner/tests_stream.js
Expand Up @@ -27,16 +27,16 @@ class TestsStream extends Readable {
}
}

fail(nesting, testNumber, name, details, directive) {
this.#emit('test:fail', { __proto__: null, name, nesting, testNumber, details, ...directive });
fail(nesting, file, testNumber, name, details, directive) {
this.#emit('test:fail', { __proto__: null, name, nesting, file, testNumber, details, ...directive });
}

ok(nesting, testNumber, name, details, directive) {
this.#emit('test:pass', { __proto__: null, name, nesting, testNumber, details, ...directive });
ok(nesting, file, testNumber, name, details, directive) {
this.#emit('test:pass', { __proto__: null, name, nesting, file, testNumber, details, ...directive });
}

plan(nesting, count) {
this.#emit('test:plan', { __proto__: null, nesting, count });
plan(nesting, file, count) {
this.#emit('test:plan', { __proto__: null, nesting, file, count });
}

getSkip(reason = undefined) {
Expand All @@ -47,12 +47,12 @@ class TestsStream extends Readable {
return { __proto__: null, todo: reason ?? true };
}

start(nesting, name) {
this.#emit('test:start', { __proto__: null, nesting, name });
start(nesting, file, name) {
this.#emit('test:start', { __proto__: null, nesting, file, name });
}

diagnostic(nesting, message) {
this.#emit('test:diagnostic', { __proto__: null, nesting, message });
diagnostic(nesting, file, message) {
this.#emit('test:diagnostic', { __proto__: null, nesting, file, message });
}

#emit(type, data) {
Expand Down
6 changes: 6 additions & 0 deletions test/fixtures/test-runner/custom_reporters/custom.js
@@ -1,6 +1,12 @@
const assert = require('assert');
const path = require('path');

module.exports = async function * customReporter(source) {
const counters = {};
for await (const event of source) {
if (event.data.file) {
assert.strictEqual(event.data.file, path.resolve(__dirname, '../reporters.js'));
}
counters[event.type] = (counters[event.type] ?? 0) + 1;
}
yield "custom.js ";
Expand Down

0 comments on commit 79f4b42

Please sign in to comment.