Repository navigation
JUnit XML failure element and attribute are incorrect when using node:assert #59593
Description
Activity
@CuriousStork Thanks for reporting this issue. Would you be open to me submitting a PR to help resolve it?
Reacted by injae kim and CuriousStorkReacted by injae kim and CuriousStorkReacted by injae kim and CuriousStork@devholic22 Hello and thank you for taking a look. I would appreciate any help with this issue 👍
Obviously, I'm not a collaborator/maintainer here, so don't know exactly how to do it properly.
Reacted by Hyunjoon Choi and injae kim@CuriousStork I created Pull Request for fix this issue.
In this PR, I’ve removed the failure attribute from the element.
As for the message field, I believe there are multiple possible approaches depending on the intended behavior, so I wanted to propose my suggestion before implementing it.Here’s the idea:
• If the error message is user-defined (generatedMessage === false), the entire message should be preserved.
• If the message is automatically generated, only the first line (before a newline) should be shown. This avoids mixing user-defined content with system-generated diagnostics.Originally, the code in lib/internal/test_runner/reporter/junit.js looks like this:
if (event.type === 'test:fail') { const error = event.data.details?.error; currentTest.children.push({ __proto__: null, nesting: event.data.nesting + 1, tag: 'failure', attrs: { __proto__: null, type: error?.failureType || error?.code, message: error?.message ?? '', }, children: [inspectWithNoCustomRetry(error, inspectOptions)], }); currentTest.failures = 1; }My proposed change is as follows:
if (event.type === 'test:fail') { const error = event.data.details?.error; let summaryMessage = ''; if (typeof error?.message === 'string') { if (error.generatedMessage === false) { summaryMessage = error.message; } else { summaryMessage = error.message.includes('\n') ? error.message.split('\n')[0] : error.message; } } currentTest.children.push({ __proto__: null, nesting: event.data.nesting + 1, tag: 'failure', attrs: { __proto__: null, type: error?.failureType || error?.code, message: summaryMessage, }, children: [inspectWithNoCustomRetry(error, inspectOptions)], }); currentTest.failures = 1; }I would appreciate your feedback on whether this approach seems reasonable, or if there’s a better way to handle error message formatting.
Reacted by injae kim and CuriousStorkReacted by injae kim and CuriousStorkReacted by injae kim and CuriousStork@devholic22 Thank you for the pull request.
I guess the cause of the issue is an incorrect attribute escaping. As I understand your idea is to use just the first line of the multiline text. I think we can use the whole multiline text, but fix its encoding/escaping for XML.
I'd suggest checking this piece of code:
node/lib/internal/test_runner/reporter/junit.js
Lines 21 to 23 in f36de72
function escapeAttribute(s = '') { return escapeContent(RegExpPrototypeSymbolReplace(/"/g, RegExpPrototypeSymbolReplace(/\n/g, s, ''), '"')); } This seems to replace
\nwith an empty string''so far. I'd try to use the correct Line Feed code for XML attributes (
) and see if it works:function escapeAttribute(s = '') { return escapeContent(RegExpPrototypeSymbolReplace(/"/g, RegExpPrototypeSymbolReplace(/\n/g, s, '
'), '"')); }
Optimistically this should put the whole multiline string into the attribute instead of its first line. I guess this should work for any alternative assertion module (like
chaietc.) and doesn't require checkinggeneratedMessage.I also noticed that
node:assertproduceserror.messagewith a trailing\n. Probably removing it viatrim()could improve the resulting XML:message: error?.message.trim() ?? ''
Hello, is anyone working on
failure:messageattribute fix? I'd like to attempt fixingescapeAttributefunction so that it escapes\ninstead of erasing it.
Version
v24.4.1
Platform
Subsystem
test
What steps will reproduce the bug?
Create any test file, like
Run the test via console
Check the report from stdout.
How often does it reproduce? Is there a required condition?
Always.
What is the expected behavior? Why is that the expected behavior?
failureelement should have a correctmessageattribute. I guess having"The value must be 0"in this example would be finetestcaseelement shouldn't have thefailureattribute.What do you see instead?
failureintestcaseelement andmessageinfailureelement are"The value must be 01 !== 0":Additional information
No response