mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
test_runner: add classname hierarchy for JUnit reporter
Signed-off-by: mag123c <diehreo@gmail.com> PR-URL: https://github.com/nodejs/node/pull/60220 Fixes: https://github.com/nodejs/node/issues/59417 Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Pietro Marchini <pietro.marchini94@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Aviv Keller <me@aviv.sh>
This commit is contained in:
1 parent
12eb296a31
commit
e2cb91d08a
7 files changed
+81
-13
No files matched your search
@@ -2,6 +2,7 @@
|
||||
const {
|
||||
ArrayFrom,
|
||||
ArrayPrototypeEvery,
|
||||
ArrayPrototypeJoin,
|
||||
ArrayPrototypePush,
|
||||
ArrayPrototypePushApply,
|
||||
ArrayPrototypeShift,
|
||||
@@ -1672,6 +1673,17 @@ class Test extends AsyncResource {
|
||||
details.passed_on_attempt = this.passedAttempt;
|
||||
}
|
||||
|
||||
// Generate classname from suite hierarchy for JUnit reporter
|
||||
if (this.parent && this.parent !== this.root) {
|
||||
const parts = [];
|
||||
for (let t = this.parent; t !== t.root; t = t.parent) {
|
||||
ArrayPrototypeUnshift(parts, t.name);
|
||||
}
|
||||
if (parts.length > 0) {
|
||||
details.classname = ArrayPrototypeJoin(parts, '.');
|
||||
}
|
||||
}
|
||||
|
||||
return { __proto__: null, details, directive };
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ class TestsStream extends Readable {
|
||||
parentId,
|
||||
details,
|
||||
tags: ArrayPrototypeSlice(tags),
|
||||
...(details.classname && { __proto__: null, classname: details.classname }),
|
||||
...loc,
|
||||
...directive,
|
||||
});
|
||||
@@ -60,6 +61,7 @@ class TestsStream extends Readable {
|
||||
parentId,
|
||||
details,
|
||||
tags: ArrayPrototypeSlice(tags),
|
||||
...(details.classname && { __proto__: null, classname: details.classname }),
|
||||
...loc,
|
||||
...directive,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
require('../../../common');
|
||||
const { suite, test } = require('node:test');
|
||||
|
||||
suite('Math', () => {
|
||||
suite('Addition', () => {
|
||||
test('adds positive numbers', () => {});
|
||||
});
|
||||
|
||||
suite('Multiplication', () => {
|
||||
test('multiplies positive numbers', () => {});
|
||||
});
|
||||
});
|
||||
|
||||
suite('String', () => {
|
||||
test('concatenates strings', () => {});
|
||||
});
|
||||
|
||||
test('standalone test', () => {});
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<testsuites>
|
||||
<testsuite name="Math" time="*" disabled="0" errors="0" tests="2" failures="0" skipped="0" timestamp="*" hostname="HOSTNAME">
|
||||
<testsuite name="Addition" time="*" disabled="0" errors="0" tests="1" failures="0" skipped="0" timestamp="*" hostname="HOSTNAME">
|
||||
<testcase name="adds positive numbers" time="*" classname="Math.Addition" file="*"/>
|
||||
</testsuite>
|
||||
<testsuite name="Multiplication" time="*" disabled="0" errors="0" tests="1" failures="0" skipped="0" timestamp="*" hostname="HOSTNAME">
|
||||
<testcase name="multiplies positive numbers" time="*" classname="Math.Multiplication" file="*"/>
|
||||
</testsuite>
|
||||
</testsuite>
|
||||
<testsuite name="String" time="*" disabled="0" errors="0" tests="1" failures="0" skipped="0" timestamp="*" hostname="HOSTNAME">
|
||||
<testcase name="concatenates strings" time="*" classname="String" file="*"/>
|
||||
</testsuite>
|
||||
<testcase name="standalone test" time="*" classname="test" file="*"/>
|
||||
<!-- tests 4 -->
|
||||
<!-- suites 4 -->
|
||||
<!-- pass 4 -->
|
||||
<!-- fail 0 -->
|
||||
<!-- cancelled 0 -->
|
||||
<!-- skipped 0 -->
|
||||
<!-- todo 0 -->
|
||||
<!-- duration_ms * -->
|
||||
</testsuites>
|
||||
+12
-12
@@ -129,7 +129,7 @@ true !== false
|
||||
<testcase name="immediate reject - passes but warns" time="*" classname="test" file="*"/>
|
||||
<testcase name="immediate resolve pass" time="*" classname="test" file="*"/>
|
||||
<testsuite name="subtest sync throw fail" time="*" disabled="0" errors="0" tests="1" failures="1" skipped="0" timestamp="*" hostname="HOSTNAME">
|
||||
<testcase name="+sync throw fail" time="*" classname="test" file="*" failure="thrown from subtest sync throw fail">
|
||||
<testcase name="+sync throw fail" time="*" classname="subtest sync throw fail" file="*" failure="thrown from subtest sync throw fail">
|
||||
<failure type="testCodeFailure" message="thrown from subtest sync throw fail">
|
||||
Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fail
|
||||
at TestContext.<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
|
||||
</failure>
|
||||
</testcase>
|
||||
<testsuite name="level 0a" time="*" disabled="0" errors="0" tests="4" failures="0" skipped="0" timestamp="*" hostname="HOSTNAME">
|
||||
<testcase name="level 1a" time="*" classname="test" file="*"/>
|
||||
<testcase name="level 1b" time="*" classname="test" file="*"/>
|
||||
<testcase name="level 1c" time="*" classname="test" file="*"/>
|
||||
<testcase name="level 1d" time="*" classname="test" file="*"/>
|
||||
<testcase name="level 1a" time="*" classname="level 0a" file="*"/>
|
||||
<testcase name="level 1b" time="*" classname="level 0a" file="*"/>
|
||||
<testcase name="level 1c" time="*" classname="level 0a" file="*"/>
|
||||
<testcase name="level 1d" time="*" classname="level 0a" file="*"/>
|
||||
</testsuite>
|
||||
<testsuite name="top level" time="*" disabled="0" errors="0" tests="2" failures="0" skipped="0" timestamp="*" hostname="HOSTNAME">
|
||||
<testcase name="+long running" time="*" classname="test" file="*"/>
|
||||
<testcase name="+long running" time="*" classname="top level" file="*"/>
|
||||
<testsuite name="+short running" time="*" disabled="0" errors="0" tests="1" failures="0" skipped="0" timestamp="*" hostname="HOSTNAME">
|
||||
<testcase name="++short running" time="*" classname="test" file="*"/>
|
||||
<testcase name="++short running" time="*" classname="top level.+short running" file="*"/>
|
||||
</testsuite>
|
||||
</testsuite>
|
||||
<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
|
||||
</testcase>
|
||||
<testcase name="callback async throw after done" time="*" classname="test" file="*"/>
|
||||
<testsuite name="only is set on subtests but not in only mode" time="*" disabled="0" errors="0" tests="3" failures="0" skipped="0" timestamp="*" hostname="HOSTNAME">
|
||||
<testcase name="running subtest 1" time="*" classname="test" file="*"/>
|
||||
<testcase name="running subtest 3" time="*" classname="test" file="*"/>
|
||||
<testcase name="running subtest 4" time="*" classname="test" file="*"/>
|
||||
<testcase name="running subtest 1" time="*" classname="only is set on subtests but not in only mode" file="*"/>
|
||||
<testcase name="running subtest 3" time="*" classname="only is set on subtests but not in only mode" file="*"/>
|
||||
<testcase name="running subtest 4" time="*" classname="only is set on subtests but not in only mode" file="*"/>
|
||||
</testsuite>
|
||||
<testcase name="custom inspect symbol fail" time="*" classname="test" file="*" failure="customized">
|
||||
<failure type="testCodeFailure" message="customized">
|
||||
@@ -289,7 +289,7 @@ Error [ERR_TEST_FAILURE]: thrown from callback async throw
|
||||
</failure>
|
||||
</testcase>
|
||||
<testsuite name="subtest sync throw fails" time="*" disabled="0" errors="0" tests="2" failures="2" skipped="0" timestamp="*" hostname="HOSTNAME">
|
||||
<testcase name="sync throw fails at first" time="*" classname="test" file="*" failure="thrown from subtest sync throw fails at first">
|
||||
<testcase name="sync throw fails at first" time="*" classname="subtest sync throw fails" file="*" failure="thrown from subtest sync throw fails at first">
|
||||
<failure type="testCodeFailure" message="thrown from subtest sync throw fails at first">
|
||||
Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at first
|
||||
at TestContext.<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
|
||||
}
|
||||
</failure>
|
||||
</testcase>
|
||||
<testcase name="sync throw fails at second" time="*" classname="test" file="*" failure="thrown from subtest sync throw fails at second">
|
||||
<testcase name="sync throw fails at second" time="*" classname="subtest sync throw fails" file="*" failure="thrown from subtest sync throw fails at second">
|
||||
<failure type="testCodeFailure" message="thrown from subtest sync throw fails at second">
|
||||
Error [ERR_TEST_FAILURE]: thrown from subtest sync throw fails at second
|
||||
at TestContext.<anonymous> (<project-root>/test/fixtures/test-runner/output/output.js:337:11) {
|
||||
|
||||
@@ -207,7 +207,7 @@ describe('node:test reporters', { concurrency: true }, () => {
|
||||
assert.match(timestamp, /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/);
|
||||
assert.ok(!Number.isNaN(Date.parse(timestamp)), `expected a valid date, got ${timestamp}`);
|
||||
assert.match(fileContents, /<testcase .*name="failing".*>\s*<failure .*type="testCodeFailure".*message="error".*>/);
|
||||
assert.match(fileContents, /<testcase .*name="ok".*classname="test".*\/>/);
|
||||
assert.match(fileContents, /<testcase .*name="ok".*classname="nested".*\/>/);
|
||||
assert.match(fileContents, /<testcase .*name="top level".*classname="test".*\/>/);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,12 @@
|
||||
// Test that the output of test-runner/output/junit_classname_hierarchy.js matches
|
||||
// test-runner/output/junit_classname_hierarchy.snapshot
|
||||
import '../common/index.mjs';
|
||||
import * as fixtures from '../common/fixtures.mjs';
|
||||
import { spawnAndAssert, junitTransform, ensureCwdIsProjectRoot } from '../common/assertSnapshot.js';
|
||||
|
||||
ensureCwdIsProjectRoot();
|
||||
await spawnAndAssert(
|
||||
fixtures.path('test-runner/output/junit_classname_hierarchy.js'),
|
||||
junitTransform,
|
||||
{ flags: ['--test-reporter=junit'] },
|
||||
);
|
||||
Reference in new issue
Block a user