Skip to content

Commit e245584

Browse files
committed
test_runner: add classname hierarchy for JUnit reporter
1 parent 731fe97 commit e245584

File tree

7 files changed

+81
-13
lines changed

7 files changed

+81
-13
lines changed

lib/internal/test_runner/test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22
const {
33
ArrayPrototypeEvery,
4+
ArrayPrototypeJoin,
45
ArrayPrototypePush,
56
ArrayPrototypePushApply,
67
ArrayPrototypeShift,
@@ -1532,6 +1533,17 @@ class Test extends AsyncResource {
15321533
details.passed_on_attempt = this.passedAttempt;
15331534
}
15341535

1536+
// Generate classname from suite hierarchy for JUnit reporter
1537+
if (this.parent && this.parent !== this.root) {
1538+
const parts = [];
1539+
for (let t = this.parent; t !== t.root; t = t.parent) {
1540+
ArrayPrototypeUnshift(parts, t.name);
1541+
}
1542+
if (parts.length > 0) {
1543+
details.classname = ArrayPrototypeJoin(parts, '.');
1544+
}
1545+
}
1546+
15351547
return { __proto__: null, details, directive };
15361548
}
15371549

lib/internal/test_runner/tests_stream.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class TestsStream extends Readable {
4141
nesting,
4242
testNumber,
4343
details,
44+
...(details.classname && { __proto__: null, classname: details.classname }),
4445
...loc,
4546
...directive,
4647
});
@@ -53,6 +54,7 @@ class TestsStream extends Readable {
5354
nesting,
5455
testNumber,
5556
details,
57+
...(details.classname && { __proto__: null, classname: details.classname }),
5658
...loc,
5759
...directive,
5860
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
'use strict';
2+
require('../../../common');
3+
const { suite, test } = require('node:test');
4+
5+
suite('Math', () => {
6+
suite('Addition', () => {
7+
test('adds positive numbers', () => {});
8+
});
9+
10+
suite('Multiplication', () => {
11+
test('multiplies positive numbers', () => {});
12+
});
13+
});
14+
15+
suite('String', () => {
16+
test('concatenates strings', () => {});
17+
});
18+
19+
test('standalone test', () => {});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<testsuites>
3+
<testsuite name="Math" time="*" disabled="0" errors="0" tests="2" failures="0" skipped="0" hostname="HOSTNAME">
4+
<testsuite name="Addition" time="*" disabled="0" errors="0" tests="1" failures="0" skipped="0" hostname="HOSTNAME">
5+
<testcase name="adds positive numbers" time="*" classname="Math.Addition" file="*"/>
6+
</testsuite>
7+
<testsuite name="Multiplication" time="*" disabled="0" errors="0" tests="1" failures="0" skipped="0" hostname="HOSTNAME">
8+
<testcase name="multiplies positive numbers" time="*" classname="Math.Multiplication" file="*"/>
9+
</testsuite>
10+
</testsuite>
11+
<testsuite name="String" time="*" disabled="0" errors="0" tests="1" failures="0" skipped="0" hostname="HOSTNAME">
12+
<testcase name="concatenates strings" time="*" classname="String" file="*"/>
13+
</testsuite>
14+
<testcase name="standalone test" time="*" classname="test" file="*"/>
15+
<!-- tests 4 -->
16+
<!-- suites 4 -->
17+
<!-- pass 4 -->
18+
<!-- fail 0 -->
19+
<!-- cancelled 0 -->
20+
<!-- skipped 0 -->
21+
<!-- todo 0 -->
22+
<!-- duration_ms * -->
23+
</testsuites>

test/fixtures/test-runner/output/junit_reporter.snapshot

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ true !== false
129129
<testcase name="immediate reject - passes but warns" time="*" classname="test" file="*"/>
130130
<testcase name="immediate resolve pass" time="*" classname="test" file="*"/>
131131
<testsuite name="subtest sync throw fail" time="*" disabled="0" errors="0" tests="1" failures="1" skipped="0" hostname="HOSTNAME">
132-
<testcase name="+sync throw fail" time="*" classname="test" file="*" failure="thrown from subtest sync throw fail">
132+
<testcase name="+sync throw fail" time="*" classname="subtest sync throw fail" file="*" failure="thrown from subtest sync throw fail">
133133
<failure type="testCodeFailure" message="thrown from subtest sync throw fail">
134134
Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail
135135
at TestContext.&lt;anonymous> (<project-root>/test/fixtures/test-runner/output/output.js:125:11)
@@ -152,15 +152,15 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail
152152
</failure>
153153
</testcase>
154154
<testsuite name="level 0a" time="*" disabled="0" errors="0" tests="4" failures="0" skipped="0" hostname="HOSTNAME">
155-
<testcase name="level 1a" time="*" classname="test" file="*"/>
156-
<testcase name="level 1b" time="*" classname="test" file="*"/>
157-
<testcase name="level 1c" time="*" classname="test" file="*"/>
158-
<testcase name="level 1d" time="*" classname="test" file="*"/>
155+
<testcase name="level 1a" time="*" classname="level 0a" file="*"/>
156+
<testcase name="level 1b" time="*" classname="level 0a" file="*"/>
157+
<testcase name="level 1c" time="*" classname="level 0a" file="*"/>
158+
<testcase name="level 1d" time="*" classname="level 0a" file="*"/>
159159
</testsuite>
160160
<testsuite name="top level" time="*" disabled="0" errors="0" tests="2" failures="0" skipped="0" hostname="HOSTNAME">
161-
<testcase name="+long running" time="*" classname="test" file="*"/>
161+
<testcase name="+long running" time="*" classname="top level" file="*"/>
162162
<testsuite name="+short running" time="*" disabled="0" errors="0" tests="1" failures="0" skipped="0" hostname="HOSTNAME">
163-
<testcase name="++short running" time="*" classname="test" file="*"/>
163+
<testcase name="++short running" time="*" classname="top level.+short running" file="*"/>
164164
</testsuite>
165165
</testsuite>
166166
<testcase name="invalid subtest - pass but subtest fails" time="*" classname="test" file="*"/>
@@ -267,9 +267,9 @@ Error [ERR_TEST_FAILURE]: thrown from callback async throw
267267
</testcase>
268268
<testcase name="callback async throw after done" time="*" classname="test" file="*"/>
269269
<testsuite name="only is set on subtests but not in only mode" time="*" disabled="0" errors="0" tests="3" failures="0" skipped="0" hostname="HOSTNAME">
270-
<testcase name="running subtest 1" time="*" classname="test" file="*"/>
271-
<testcase name="running subtest 3" time="*" classname="test" file="*"/>
272-
<testcase name="running subtest 4" time="*" classname="test" file="*"/>
270+
<testcase name="running subtest 1" time="*" classname="only is set on subtests but not in only mode" file="*"/>
271+
<testcase name="running subtest 3" time="*" classname="only is set on subtests but not in only mode" file="*"/>
272+
<testcase name="running subtest 4" time="*" classname="only is set on subtests but not in only mode" file="*"/>
273273
</testsuite>
274274
<testcase name="custom inspect symbol fail" time="*" classname="test" file="*" failure="customized">
275275
<failure type="testCodeFailure" message="customized">
@@ -289,7 +289,7 @@ Error [ERR_TEST_FAILURE]: thrown from callback async throw
289289
</failure>
290290
</testcase>
291291
<testsuite name="subtest sync throw fails" time="*" disabled="0" errors="0" tests="2" failures="2" skipped="0" hostname="HOSTNAME">
292-
<testcase name="sync throw fails at first" time="*" classname="test" file="*" failure="thrown from subtest sync throw fails at first">
292+
<testcase name="sync throw fails at first" time="*" classname="subtest sync throw fails" file="*" failure="thrown from subtest sync throw fails at first">
293293
<failure type="testCodeFailure" message="thrown from subtest sync throw fails at first">
294294
Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at first
295295
at TestContext.&lt;anonymous> (<project-root>/test/fixtures/test-runner/output/output.js:334:11)
@@ -304,7 +304,7 @@ Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at first
304304
}
305305
</failure>
306306
</testcase>
307-
<testcase name="sync throw fails at second" time="*" classname="test" file="*" failure="thrown from subtest sync throw fails at second">
307+
<testcase name="sync throw fails at second" time="*" classname="subtest sync throw fails" file="*" failure="thrown from subtest sync throw fails at second">
308308
<failure type="testCodeFailure" message="thrown from subtest sync throw fails at second">
309309
Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at second
310310
at TestContext.&lt;anonymous> (<project-root>/test/fixtures/test-runner/output/output.js:337:11) {

test/parallel/test-runner-reporters.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ describe('node:test reporters', { concurrency: true }, () => {
201201
const fileContents = fs.readFileSync(file, 'utf8');
202202
assert.match(fileContents, /<testsuite .*name="nested".*tests="2".*failures="1".*skipped="0".*>/);
203203
assert.match(fileContents, /<testcase .*name="failing".*>\s*<failure .*type="testCodeFailure".*message="error".*>/);
204-
assert.match(fileContents, /<testcase .*name="ok".*classname="test".*\/>/);
204+
assert.match(fileContents, /<testcase .*name="ok".*classname="nested".*\/>/);
205205
assert.match(fileContents, /<testcase .*name="top level".*classname="test".*\/>/);
206206
});
207207
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Test that the output of test-runner/output/junit_classname_hierarchy.js matches
2+
// test-runner/output/junit_classname_hierarchy.snapshot
3+
import '../common/index.mjs';
4+
import * as fixtures from '../common/fixtures.mjs';
5+
import { spawnAndAssert, junitTransform, ensureCwdIsProjectRoot } from '../common/assertSnapshot.js';
6+
7+
ensureCwdIsProjectRoot();
8+
await spawnAndAssert(
9+
fixtures.path('test-runner/output/junit_classname_hierarchy.js'),
10+
junitTransform,
11+
{ flags: ['--test-reporter=junit'] },
12+
);

0 commit comments

Comments
 (0)