Skip to content

Commit

Permalink
feat: copy duration to root from suite (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
ASaiAnudeep authored Apr 8, 2024
1 parent 9400bef commit db4b903
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 26 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "test-results-parser",
"version": "0.1.10",
"version": "0.1.11",
"description": "Parse test results from JUnit, TestNG, xUnit, cucumber and many more",
"main": "src/index.js",
"types": "./src/index.d.ts",
Expand Down
37 changes: 21 additions & 16 deletions src/parsers/junit.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function getTestCase(rawCase, suite_meta) {
test_case.duration = rawCase["@_time"] * 1000;
test_case.meta_data = new Map(suite_meta);
setAttachments(rawCase, test_case);
setMetaData(rawCase, test_case);
setMetaData(rawCase, test_case);
if (rawCase.failure && rawCase.failure.length > 0) {
test_case.status = 'FAIL';
test_case.setFailure(rawCase.failure[0]["@_message"]);
Expand Down Expand Up @@ -50,7 +50,7 @@ function getTestSuite(rawSuite) {

/**
* @param {import('./junit.result').JUnitTestSuite | import('./junit.result').JUnitTestCase} rawElement
* @param {TestCase | TestSuite} test_element
* @param {TestCase | TestSuite} test_element
*/
function setMetaData(rawElement, test_element) {
if (rawElement.properties && rawElement.properties.property.length > 0) {
Expand Down Expand Up @@ -88,15 +88,15 @@ function setAttachments(rawCase, test_element) {

if (filePath.length > 0) {
const attachment = new TestAttachment();
attachment.path = filePath;
attachment.path = filePath;
test_element.attachments.push(attachment);
}
}
}
}

/**
* @param {TestResult} result
* @param {TestResult} result
*/
function setAggregateResults(result) {
if (Number.isNaN(result.passed) || Number.isNaN(result.failed)) {
Expand All @@ -105,30 +105,32 @@ function setAggregateResults(result) {
let failed = 0;
let errors = 0;
let skipped = 0;
let duration = 0;
result.suites.forEach(_suite => {
total = _suite.total + total;
passed = _suite.passed + passed;
failed = _suite.failed + failed;
errors = _suite.errors + errors;
skipped = _suite.skipped + skipped;
duration = _suite.duration + duration;
});
result.passed = passed;
result.failed = failed;
result.errors = errors;
result.skipped = skipped;
result.total = total;
if (Number.isNaN(result.duration)) {
result.duration = duration;
}
}
if (Number.isNaN(result.duration)) {
let duration = 0;
result.suites.forEach(_suite => {
duration = _suite.duration + duration;
});
result.duration = duration;
}
}

/**
*
* @param {import('./junit.result').JUnitResultJson} json
* @returns
*
* @param {import('./junit.result').JUnitResultJson} json
* @returns
*/
function getTestResult(json) {
const result = new TestResult();
Expand All @@ -147,18 +149,21 @@ function getTestResult(json) {
result.total = result.total - result.skipped;
result.passed = result.total - result.failed - result.errors;
result.duration = rawResult["@_time"] * 1000;
if (json["testsuites"]) { // top-level element is testsuites
// top-level element is testsuites
if (json["testsuites"]) {
const rawSuites = rawResult["testsuite"];
if (!(typeof rawSuites === "undefined")) { // Don't filter if there are no testsuite objects
// Don't filter if there are no testsuite objects
if (!(typeof rawSuites === "undefined")) {
const filteredSuites = rawSuites.filter(suite => suite.testcase);
for (let i = 0; i < filteredSuites.length; i++) {
result.suites.push(getTestSuite(filteredSuites[i]));
}
}
} else { // top level element is testsuite
} else {
// top level element is testsuite
result.suites.push(getTestSuite(rawResult));
}

setAggregateResults(result);
result.status = result.total === result.passed ? 'PASS' : 'FAIL';
return result;
Expand Down
31 changes: 31 additions & 0 deletions tests/data/junit/wdio/results-0-0.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="4" failures="0" errors="0" skipped="0">
<testsuite name="X Source to Y Destination" timestamp="2024-04-08T14:48:58" time="108.995" tests="4" failures="0" errors="0" skipped="0">
<properties>
<property name="specId" value="0"/>
<property name="featureName" value="X Source to Y Destination"/>
<property name="capabilities" value="chrome.123_0_6312_59.windows"/>
<property name="featureFile" value="file://./src/features/controlplane-team/cloud-extract-source-warehouse-destination.feature"/>
</properties>
<testcase classname="CucumberJUnitReport-chrome.123_0_6312_59.windows.X Source to Y Destination" name="User creates an Amplitude X source" time="51.099">
<system-out><![CDATA[
✅ Given I open the site "/login"✅ And I log in with "enterprise" account✅ And I visit the url "/directory"✅ When I add a source of type "Amplitude" with name "Src_Amp" with details✅ Then I expect to be in the "Src_Amp" page
]]></system-out>
</testcase>
<testcase classname="CucumberJUnitReport-chrome.123_0_6312_59.windows.X Source to Y Destination" name="User creates a Snowflake warehouse destination" time="41.444">
<system-out><![CDATA[
✅ And I visit the url "/directory"✅ When I add a destination of type "Snowflake" with name "Dst_SNFLK" with details✅ Then I expect to be in the "Dst_SNFLK" page
]]></system-out>
</testcase>
<testcase classname="CucumberJUnitReport-chrome.123_0_6312_59.windows.X Source to Y Destination" name="User removes connection deletes warehouse destination" time="8.294">
<system-out><![CDATA[
✅ Given I navigate to destination "Dst_SNFLK"✅ When I disconnect source "Src_Amp" from destination✅ And I delete the current destination✅ Then I expect to be in the "Destinations" page
]]></system-out>
</testcase>
<testcase classname="CucumberJUnitReport-chrome.123_0_6312_59.windows.X Source to Y Destination" name="User deletes X source" time="7.642">
<system-out><![CDATA[
✅ Given I navigate to source "Src_Amp"✅ When I delete the current source✅ Then I expect to be in the "Sources" page
]]></system-out>
</testcase>
</testsuite>
</testsuites>
36 changes: 36 additions & 0 deletions tests/data/junit/wdio/results-0-1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites tests="5" failures="0" errors="0" skipped="0">
<testsuite name="X Source to Y Destination" timestamp="2024-04-08T14:48:59" time="48.494" tests="5" failures="0" errors="0" skipped="0">
<properties>
<property name="specId" value="0"/>
<property name="featureName" value="X Source to Y Destination"/>
<property name="capabilities" value="chrome.123_0_6312_59.windows"/>
<property name="featureFile" value="file://./src/features/controlplane-team/event-stream.feature"/>
</properties>
<testcase classname="CucumberJUnitReport-chrome.123_0_6312_59.windows.X Source to Y Destination" name="User creates a HTTP X source" time="17.227">
<system-out><![CDATA[
✅ Given I open the site "/login"✅ And I log in with "enterprise" account✅ And I visit the url "/directory"✅ When I add a source of type "HTTP" with name "Src_http"✅ Then I expect to be in the "Src_http" page
]]></system-out>
</testcase>
<testcase classname="CucumberJUnitReport-chrome.123_0_6312_59.windows.X Source to Y Destination" name="User creates a cloud destination of type Amplitude and connects to HTTP X source" time="12.496">
<system-out><![CDATA[
✅ And I visit the url "/directory"✅ And I add a destination of type "Amplitude" with name "Dest_amp", connected to source with name "Src_http"
]]></system-out>
</testcase>
<testcase classname="CucumberJUnitReport-chrome.123_0_6312_59.windows.X Source to Y Destination" name="User deletes connection" time="5.719">
<system-out><![CDATA[
✅ When I navigate to source "Src_http"✅ And I disconnect destination "Dest_amp" from source
]]></system-out>
</testcase>
<testcase classname="CucumberJUnitReport-chrome.123_0_6312_59.windows.X Source to Y Destination" name="User deletes destination" time="5.755">
<system-out><![CDATA[
✅ And I navigate to destination "Dest_amp"✅ And I delete the current destination✅ Then I expect to be in the "Destinations" page
]]></system-out>
</testcase>
<testcase classname="CucumberJUnitReport-chrome.123_0_6312_59.windows.X Source to Y Destination" name="User deletes source" time="7.061">
<system-out><![CDATA[
✅ When I navigate to source "Src_http"✅ And I delete the current source✅ Then I expect to be in the "Sources" page
]]></system-out>
</testcase>
</testsuite>
</testsuites>
23 changes: 16 additions & 7 deletions tests/parser.junit.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ const assert = require('assert');
const path = require('path');

describe('Parser - JUnit', () => {

const testDataPath = "tests/data/junit"

it('single suite with single test', () => {
const result = parse({ type: 'junit', files: [`${testDataPath}/single-suite.xml`] });
assert.deepEqual(result, {
Expand Down Expand Up @@ -450,7 +450,7 @@ describe('Parser - JUnit', () => {

it('parse spekt/junit.testlogger', () => {
const result = parse({ type: 'junit', files: [`${testDataPath}/junit.testlogger.xml`] });
var inheritedProperties = new Map([ ["hostname", "REDACTED"] ]);
var inheritedProperties = new Map([["hostname", "REDACTED"]]);
assert.deepEqual(result, {
id: "",
name: "",
Expand Down Expand Up @@ -574,10 +574,10 @@ describe('Parser - JUnit', () => {
let absolutePath = path.resolve(relativePath);
const result1 = parse({ type: 'junit', files: [absolutePath] });
assert.notEqual(null, result1);
const result2 = parse({ type: 'junit', files: [relativePath]});
const result2 = parse({ type: 'junit', files: [relativePath] });
assert.notEqual(null, result2);
});

it('meta-data from suite merged with testcase', () => {
const result = parse({ type: 'junit', files: ['tests/data/junit/multiple-suites-properties.xml'] });

Expand All @@ -594,7 +594,7 @@ describe('Parser - JUnit', () => {

it('include hostname in meta-data from suite and testcase', () => {
const result = parse({ type: 'junit', files: ['tests/data/junit/playwright.xml'] });

assert.equal(result.suites[0].meta_data.get("hostname"), "chromium");
assert.equal(result.suites[0].cases[0].meta_data.get("hostname"), "chromium");
assert.equal(result.suites[0].cases[1].meta_data.get("hostname"), "chromium");
Expand All @@ -606,7 +606,7 @@ describe('Parser - JUnit', () => {
assert.equal(result.suites[2].meta_data.get("hostname"), "webkit");
assert.equal(result.suites[2].cases[0].meta_data.get("hostname"), "webkit");
assert.equal(result.suites[2].cases[1].meta_data.get("hostname"), "webkit");

});

it('parse system.out to locate attachments', () => {
Expand All @@ -628,4 +628,13 @@ describe('Parser - JUnit', () => {
assert.equal(result.suites[0].cases[3].attachments.length, 0);
});

it('wdio - multiple files', () => {
const result = parse({ type: 'junit', files: [`${testDataPath}/wdio/*.xml`] });
assert.equal(result.total, 9);
assert.equal(result.passed, 9);
assert.equal(result.failed, 0);
assert.equal(result.duration, 157489);
assert.equal(result.status, 'PASS');
});

});

0 comments on commit db4b903

Please sign in to comment.