From b18e3b124c01681e283e3d80a184a205bec4aeff Mon Sep 17 00:00:00 2001 From: Bernhard Weber Date: Wed, 24 Apr 2024 11:42:55 +0200 Subject: [PATCH 1/8] test: log --- index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/index.js b/index.js index 060ff9d..aab9ca8 100644 --- a/index.js +++ b/index.js @@ -272,6 +272,7 @@ function MochaJUnitReporter(runner, options) { } this._runner.on('end', function(){ + console.log('flush'); this.flush(testsuites); }.bind(this)); } From 282a202b8dcd2682d62c35da6922331a8f15d938 Mon Sep 17 00:00:00 2001 From: Bernhard Weber Date: Wed, 24 Apr 2024 12:26:04 +0200 Subject: [PATCH 2/8] feat: add retries to xml --- index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index aab9ca8..68bf5e0 100644 --- a/index.js +++ b/index.js @@ -272,7 +272,6 @@ function MochaJUnitReporter(runner, options) { } this._runner.on('end', function(){ - console.log('flush'); this.flush(testsuites); }.bind(this)); } @@ -332,7 +331,8 @@ MochaJUnitReporter.prototype.getTestcaseData = function(test, err) { name: flipClassAndName ? classname : name, time: (typeof test.duration === 'undefined') ? 0 : test.duration / 1000, classname: flipClassAndName ? name : classname - } + }, + retries: test._currentRetry }] }; @@ -469,10 +469,12 @@ MochaJUnitReporter.prototype.getXml = function(testsuites) { _suiteAttr.timestamp = new Date(_suiteAttr.timestamp).toISOString().slice(0, -5); _suiteAttr.failures = 0; _suiteAttr.skipped = 0; + _suiteAttr.retries = 0; _cases.forEach(function(testcase) { var lastNode = testcase.testcase[testcase.testcase.length - 1]; + _suiteAttr.retries = Number('retries' in lastNode); _suiteAttr.skipped += Number('skipped' in lastNode); _suiteAttr.failures += Number('failure' in lastNode); if (typeof testcase.testcase[0]._attr.time === 'number') { From 89cb5a788d824c4c053f03c79b6c5d09c32f3cef Mon Sep 17 00:00:00 2001 From: Bernhard Weber Date: Mon, 6 May 2024 13:53:43 +0200 Subject: [PATCH 3/8] feat: move retries to attributes, so it gets displayed in both testcases and testsuite --- index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 68bf5e0..ed1fbed 100644 --- a/index.js +++ b/index.js @@ -330,9 +330,9 @@ MochaJUnitReporter.prototype.getTestcaseData = function(test, err) { _attr: { name: flipClassAndName ? classname : name, time: (typeof test.duration === 'undefined') ? 0 : test.duration / 1000, - classname: flipClassAndName ? name : classname - }, - retries: test._currentRetry + classname: flipClassAndName ? name : classname, + retries: test._currentRetry + } }] }; @@ -474,7 +474,7 @@ MochaJUnitReporter.prototype.getXml = function(testsuites) { _cases.forEach(function(testcase) { var lastNode = testcase.testcase[testcase.testcase.length - 1]; - _suiteAttr.retries = Number('retries' in lastNode); + _suiteAttr.retries = Number('retries' in lastNode._attr); _suiteAttr.skipped += Number('skipped' in lastNode); _suiteAttr.failures += Number('failure' in lastNode); if (typeof testcase.testcase[0]._attr.time === 'number') { From 36b9ccca5489dfb9b437311a26a399748b7cdeae Mon Sep 17 00:00:00 2001 From: Bernhard Weber Date: Mon, 6 May 2024 13:57:12 +0200 Subject: [PATCH 4/8] fix: sum up retries correctly --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index ed1fbed..af9f0c4 100644 --- a/index.js +++ b/index.js @@ -474,7 +474,7 @@ MochaJUnitReporter.prototype.getXml = function(testsuites) { _cases.forEach(function(testcase) { var lastNode = testcase.testcase[testcase.testcase.length - 1]; - _suiteAttr.retries = Number('retries' in lastNode._attr); + _suiteAttr.retries += Number('retries' in lastNode._attr); _suiteAttr.skipped += Number('skipped' in lastNode); _suiteAttr.failures += Number('failure' in lastNode); if (typeof testcase.testcase[0]._attr.time === 'number') { From 5055fe63742a87c76eaab7ab6862639611b2fe2c Mon Sep 17 00:00:00 2001 From: Bernhard Weber Date: Mon, 6 May 2024 14:59:18 +0200 Subject: [PATCH 5/8] fix: sum up retries correctly --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index af9f0c4..0b96f58 100644 --- a/index.js +++ b/index.js @@ -474,12 +474,14 @@ MochaJUnitReporter.prototype.getXml = function(testsuites) { _cases.forEach(function(testcase) { var lastNode = testcase.testcase[testcase.testcase.length - 1]; - _suiteAttr.retries += Number('retries' in lastNode._attr); _suiteAttr.skipped += Number('skipped' in lastNode); _suiteAttr.failures += Number('failure' in lastNode); if (typeof testcase.testcase[0]._attr.time === 'number') { testcase.testcase[0]._attr.time = testcase.testcase[0]._attr.time.toFixed(3); } + if (typeof testcase.testcase[0]._attr.retries === 'number') { + _suiteAttr.retries += testcase.testcase[0]._attr.retries; + } }); if (antMode) { From 7f478f889fec2709da378b27e01f57cba7e37155 Mon Sep 17 00:00:00 2001 From: Bernhard Weber Date: Mon, 13 May 2024 23:13:52 +0200 Subject: [PATCH 6/8] feat: add more details to retries failures --- index.js | 61 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/index.js b/index.js index 0b96f58..b0cf421 100644 --- a/index.js +++ b/index.js @@ -194,6 +194,33 @@ function getJenkinsClassname (test, options) { return titles.join(options.suiteTitleSeparatedBy); } +function appendFormattedErrorMessageToTestcase(testcase, err, self) { + var message; + if (err.message && typeof err.message.toString === 'function') { + message = err.message + ''; + } else if (typeof err.inspect === 'function') { + message = err.inspect() + ''; + } else { + message = ''; + } + var failureMessage = err.stack || message; + if (!Base.hideDiff && err.expected !== undefined) { + var oldUseColors = Base.useColors; + Base.useColors = false; + failureMessage += "\n" + Base.generateDiff(err.actual, err.expected); + Base.useColors = oldUseColors; + } + var failureElement = { + _attr: { + message: self.removeInvalidCharacters(message) || '', + type: err.name || '' + }, + _cdata: self.removeInvalidCharacters(failureMessage) + }; + + testcase.testcase.push({failure: failureElement}); +} + /** * JUnit reporter for mocha.js. * @module mocha-junit-reporter @@ -331,7 +358,8 @@ MochaJUnitReporter.prototype.getTestcaseData = function(test, err) { name: flipClassAndName ? classname : name, time: (typeof test.duration === 'undefined') ? 0 : test.duration / 1000, classname: flipClassAndName ? name : classname, - retries: test._currentRetry + retries: test._currentRetry, + conclusion: err ? 'failure' : 'success', } }] }; @@ -357,31 +385,14 @@ MochaJUnitReporter.prototype.getTestcaseData = function(test, err) { testcase.testcase.push({'system-err': this.removeInvalidCharacters(stripAnsi(test.consoleErrors.join('\n')))}); } - if (err) { - var message; - if (err.message && typeof err.message.toString === 'function') { - message = err.message + ''; - } else if (typeof err.inspect === 'function') { - message = err.inspect() + ''; - } else { - message = ''; + if (test.prevAttempts) { + const self = this; + test.prevAttempts.forEach(function (attempt) { + appendFormattedErrorMessageToTestcase(testcase, attempt.err, self); + }) } - var failureMessage = err.stack || message; - if (!Base.hideDiff && err.expected !== undefined) { - var oldUseColors = Base.useColors; - Base.useColors = false; - failureMessage += "\n" + Base.generateDiff(err.actual, err.expected); - Base.useColors = oldUseColors; - } - var failureElement = { - _attr: { - message: this.removeInvalidCharacters(message) || '', - type: err.name || '' - }, - _cdata: this.removeInvalidCharacters(failureMessage) - }; - - testcase.testcase.push({failure: failureElement}); + if (err) { + appendFormattedErrorMessageToTestcase(testcase, err, this); } return testcase; }; From a048b1176cc542a4e887e1642b9f9c7c95452758 Mon Sep 17 00:00:00 2001 From: Bernhard Weber Date: Thu, 16 May 2024 18:28:51 +0200 Subject: [PATCH 7/8] fix: append failure nodes only in final fail case --- index.js | 54 ++++++++++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/index.js b/index.js index b0cf421..ce808ca 100644 --- a/index.js +++ b/index.js @@ -194,31 +194,29 @@ function getJenkinsClassname (test, options) { return titles.join(options.suiteTitleSeparatedBy); } -function appendFormattedErrorMessageToTestcase(testcase, err, self) { - var message; - if (err.message && typeof err.message.toString === 'function') { - message = err.message + ''; - } else if (typeof err.inspect === 'function') { - message = err.inspect() + ''; - } else { - message = ''; - } - var failureMessage = err.stack || message; - if (!Base.hideDiff && err.expected !== undefined) { - var oldUseColors = Base.useColors; - Base.useColors = false; - failureMessage += "\n" + Base.generateDiff(err.actual, err.expected); - Base.useColors = oldUseColors; - } - var failureElement = { - _attr: { - message: self.removeInvalidCharacters(message) || '', - type: err.name || '' - }, - _cdata: self.removeInvalidCharacters(failureMessage) - }; - - testcase.testcase.push({failure: failureElement}); +function formatErrorMessage(err, removeInvalidCharacters) { + var message; + if (err.message && typeof err.message.toString === 'function') { + message = err.message + ''; + } else if (typeof err.inspect === 'function') { + message = err.inspect() + ''; + } else { + message = ''; + } + var failureMessage = err.stack || message; + if (!Base.hideDiff && err.expected !== undefined) { + var oldUseColors = Base.useColors; + Base.useColors = false; + failureMessage += "\n" + Base.generateDiff(err.actual, err.expected); + Base.useColors = oldUseColors; + } + return { + _attr: { + message: removeInvalidCharacters(message) || '', + type: err.name || '' + }, + _cdata: removeInvalidCharacters(failureMessage) + }; } /** @@ -388,11 +386,11 @@ MochaJUnitReporter.prototype.getTestcaseData = function(test, err) { if (test.prevAttempts) { const self = this; test.prevAttempts.forEach(function (attempt) { - appendFormattedErrorMessageToTestcase(testcase, attempt.err, self); + testcase.testcase.push({flakyFailure: formatErrorMessage(attempt.err, self.removeInvalidCharacters)}); }) - } + } if (err) { - appendFormattedErrorMessageToTestcase(testcase, err, this); + testcase.testcase.push({failure: formatErrorMessage(err, this.removeInvalidCharacters)}); } return testcase; }; From 90e8c15999a1bf8dde3583b0df77e36401b04096 Mon Sep 17 00:00:00 2001 From: Bernhard Weber Date: Tue, 21 May 2024 16:42:41 +0200 Subject: [PATCH 8/8] chore: fix linting & tests, add documentation --- index.js | 2 +- test/mock-results.js | 32 +++++++++++++++++++++++--------- test/resources/JUnit.xsd | 15 +++++++++++++++ test/resources/jenkins-junit.xsd | 3 +++ 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/index.js b/index.js index ce808ca..13ddb16 100644 --- a/index.js +++ b/index.js @@ -387,7 +387,7 @@ MochaJUnitReporter.prototype.getTestcaseData = function(test, err) { const self = this; test.prevAttempts.forEach(function (attempt) { testcase.testcase.push({flakyFailure: formatErrorMessage(attempt.err, self.removeInvalidCharacters)}); - }) + }); } if (err) { testcase.testcase.push({failure: formatErrorMessage(err, this.removeInvalidCharacters)}); diff --git a/test/mock-results.js b/test/mock-results.js index 839ddca..848c5f2 100644 --- a/test/mock-results.js +++ b/test/mock-results.js @@ -21,7 +21,8 @@ module.exports = function(stats, options) { timestamp: "1970-01-01T00:00:00", // ISO timestamp truncated to the second tests: "0", failures: "0", - time: "0.000" + time: "0.000", + retries: "0" } } ] @@ -34,7 +35,8 @@ module.exports = function(stats, options) { timestamp: "1970-01-01T00:00:00", tests: "3", failures: "2", - time: "100.001" + time: "100.001", + retries: "0" } }, { @@ -42,7 +44,9 @@ module.exports = function(stats, options) { _attr: { name: "Foo Bar can weez the juice", classname: "can weez the juice", - time: "0.101" + time: "0.101", + retries: "0", + conclusion: "success" } } }, @@ -52,7 +56,9 @@ module.exports = function(stats, options) { _attr: { name: "Foo Bar can narfle the garthog", classname: "can narfle the garthog", - time: "2.002" + time: "2.002", + retries: "0", + conclusion: "failure" } }, { @@ -72,7 +78,9 @@ module.exports = function(stats, options) { _attr: { name: "Foo Bar can behave like a flandip", classname: "can behave like a flandip", - time: "30.003" + time: "30.003", + retries: "0", + conclusion: "failure" } }, { @@ -96,7 +104,8 @@ module.exports = function(stats, options) { timestamp: "1970-01-01T00:01:40", // new Date(100001).toISOString().slice(0, -5) tests: "1", failures: "0", - time: "400.005" + time: "400.005", + retries: "0" } }, { @@ -104,7 +113,9 @@ module.exports = function(stats, options) { _attr: { name: "Another suite! works", classname: "works", - time: "400.004" + time: "400.004", + retries: "0", + conclusion: "success" } } } @@ -148,7 +159,8 @@ module.exports = function(stats, options) { tests: "1", failures: "0", skipped: "1", - time: "0.000" + time: "0.000", + retries: "0" } }, { @@ -157,7 +169,9 @@ module.exports = function(stats, options) { _attr: { name: "Pending suite! pending", classname: "pending", - time: "0.000" + time: "0.000", + retries: "0", + conclusion: "success" } }, { diff --git a/test/resources/JUnit.xsd b/test/resources/JUnit.xsd index 44b841f..d990c06 100644 --- a/test/resources/JUnit.xsd +++ b/test/resources/JUnit.xsd @@ -129,6 +129,16 @@ Permission to waive conditions of this license may be requested from Windy Road Time taken (in seconds) to execute the test + + + Number of times the testcase was re-run. + + + + + Conclusion of the testcase: success or failure + + @@ -192,6 +202,11 @@ Permission to waive conditions of this license may be requested from Windy Road The total number of tests in the suite that errorrd. An errored test is one that had an unanticipated problem. e.g., an unchecked throwable; or a problem with the implementation of the test. + + + The total number of tests in the suite that were rerun. + + Time taken (in seconds) to execute the tests in the suite diff --git a/test/resources/jenkins-junit.xsd b/test/resources/jenkins-junit.xsd index e8228ac..f89d4ed 100644 --- a/test/resources/jenkins-junit.xsd +++ b/test/resources/jenkins-junit.xsd @@ -75,6 +75,8 @@ + + @@ -90,6 +92,7 @@ +