From 1688dd4f9679f0e4a8fa11b2f59558098d66208e Mon Sep 17 00:00:00 2001 From: Anudeep Date: Sat, 18 Sep 2021 12:33:37 +0530 Subject: [PATCH] added support for JUnit --- README.md | 8 ++ package-lock.json | 4 +- package.json | 2 +- src/parsers/index.js | 7 +- src/parsers/junit.js | 50 +++++++ src/parsers/testng.js | 4 +- tests/data/junit/empty-suite.xml | 12 ++ tests/data/junit/multiple-suites.xml | 17 +++ .../junit/{default.xml => single-suite.xml} | 6 +- tests/data/junit/skipped-tests.xml | 10 ++ tests/parser.junit.spec.js | 134 ++++++++++++++++++ tests/parser.testng.spec.js | 8 +- 12 files changed, 247 insertions(+), 15 deletions(-) create mode 100644 src/parsers/junit.js create mode 100644 tests/data/junit/empty-suite.xml create mode 100644 tests/data/junit/multiple-suites.xml rename tests/data/junit/{default.xml => single-suite.xml} (53%) create mode 100644 tests/data/junit/skipped-tests.xml create mode 100644 tests/parser.junit.spec.js diff --git a/README.md b/README.md index 4c30df3..d928036 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ # test-results-parser + Parse test results from JUnit, TestNG, xUnit and many more + +## Support + +| Result Type | Support | +|-------------|---------| +| TestNG | ✅ | +| JUnit | ✅ | diff --git a/package-lock.json b/package-lock.json index 4511e37..f2ab7d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { - "name": "@trr/parser", - "version": "0.0.1", + "name": "test-results-parser", + "version": "0.0.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 54d43db..a9a4e8c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "test-results-parser", - "version": "0.0.1", + "version": "0.0.2", "description": "Parse test results from JUnit, TestNG, xUnit and many more", "main": "src/index.js", "types": "./src/index.d.ts", diff --git a/src/parsers/index.js b/src/parsers/index.js index a300efc..6ce1bd7 100644 --- a/src/parsers/index.js +++ b/src/parsers/index.js @@ -1,11 +1,14 @@ const testng = require('./testng'); +const junit = require('./junit'); function parse(options) { switch (options.type) { case 'testng': - return testng.parse(options) + return testng.parse(options); + case 'junit': + return junit.parse(options); default: - throw `UnKnown Result Type - ${options.type}` + throw `UnSupported Result Type - ${options.type}`; } } diff --git a/src/parsers/junit.js b/src/parsers/junit.js new file mode 100644 index 0000000..86d7d72 --- /dev/null +++ b/src/parsers/junit.js @@ -0,0 +1,50 @@ +const { getJsonFromXMLFile } = require('../helpers/helper'); + +const TestResult = require('../models/TestResult'); +const TestSuite = require('../models/TestSuite'); + +function getTestSuite(rawSuite) { + const suite = new TestSuite(); + suite.name = rawSuite["@_name"]; + suite.total = rawSuite["@_tests"]; + suite.failed = rawSuite["@_failures"]; + suite.passed = suite.total - suite.failed; + suite.duration = rawSuite["@_time"] * 1000; + suite.status = suite.total === suite.passed ? 'PASS' : 'FAIL'; + return suite; +} + +function getTestResult(json) { + const result = new TestResult(); + const rawResult = json["testsuites"][0]; + result.name = rawResult["@_name"]; + result.total = rawResult["@_tests"]; + result.failed = rawResult["@_failures"]; + const errors = rawResult["@_errors"]; + if (errors) { + result.errors = errors; + } + const skipped = rawResult["@_skipped"]; + if (skipped) { + result.skipped = skipped; + } + result.total = result.total - result.skipped; + result.passed = result.total - result.failed - result.errors; + result.duration = rawResult["@_time"] * 1000; + const rawSuites = rawResult["testsuite"]; + const filteredSuites = rawSuites.filter(suite => suite.testcase); + for (let i = 0; i < filteredSuites.length; i++) { + result.suites.push(getTestSuite(filteredSuites[i])); + } + result.status = result.total === result.passed ? 'PASS' : 'FAIL'; + return result; +} + +function parse(options) { + const json = getJsonFromXMLFile(options.files[0]); + return getTestResult(json); +} + +module.exports = { + parse +} \ No newline at end of file diff --git a/src/parsers/testng.js b/src/parsers/testng.js index eca9fdd..14eb8ac 100644 --- a/src/parsers/testng.js +++ b/src/parsers/testng.js @@ -62,7 +62,6 @@ function parse(options) { result.name = _suite.name; } } - result.status = result.total === result.passed ? 'PASS' : 'FAIL'; } else if (suitesWithTests.length === 1) { const suite = suitesWithTests[0]; result.name = suite['@_name']; @@ -71,11 +70,10 @@ function parse(options) { for (let i = 0; i < rawTests.length; i++) { result.suites.push(getTestSuiteFromTest(rawTests[i])); } - result.status = result.total === result.passed ? 'PASS' : 'FAIL'; - } else { console.log("No suites with tests found"); } + result.status = result.total === result.passed ? 'PASS' : 'FAIL'; return result; } diff --git a/tests/data/junit/empty-suite.xml b/tests/data/junit/empty-suite.xml new file mode 100644 index 0000000..6eed759 --- /dev/null +++ b/tests/data/junit/empty-suite.xml @@ -0,0 +1,12 @@ + + + + + + + + Some Text + + + + \ No newline at end of file diff --git a/tests/data/junit/multiple-suites.xml b/tests/data/junit/multiple-suites.xml new file mode 100644 index 0000000..87df89b --- /dev/null +++ b/tests/data/junit/multiple-suites.xml @@ -0,0 +1,17 @@ + + + + + + Some Text + + + + + + + Some Text + + + + \ No newline at end of file diff --git a/tests/data/junit/default.xml b/tests/data/junit/single-suite.xml similarity index 53% rename from tests/data/junit/default.xml rename to tests/data/junit/single-suite.xml index 6ea2134..bdca815 100644 --- a/tests/data/junit/default.xml +++ b/tests/data/junit/single-suite.xml @@ -1,7 +1,7 @@ - - - + + + Some Text diff --git a/tests/data/junit/skipped-tests.xml b/tests/data/junit/skipped-tests.xml new file mode 100644 index 0000000..b53f423 --- /dev/null +++ b/tests/data/junit/skipped-tests.xml @@ -0,0 +1,10 @@ + + + + + + Some Text + + + + \ No newline at end of file diff --git a/tests/parser.junit.spec.js b/tests/parser.junit.spec.js new file mode 100644 index 0000000..da40366 --- /dev/null +++ b/tests/parser.junit.spec.js @@ -0,0 +1,134 @@ +const { parse } = require('../src'); +const assert = require('assert'); + +describe('Parser - JUnit', () => { + + it('single suite with single test', () => { + const result = parse({ type: 'junit', files: ['tests/data/junit/single-suite.xml'] }); + assert.deepEqual(result, { + id: '', + name: 'result name', + total: 1, + passed: 0, + failed: 1, + errors: 0, + skipped: 0, + duration: 10000, + status: 'FAIL', + suites: [ + { + id: '', + name: 'suite name', + total: 1, + passed: 0, + failed: 1, + errors: 0, + skipped: 0, + duration: 10000, + status: 'FAIL', + cases: [] + } + ] + }); + }); + + it('empty suite with single test', () => { + const result = parse({ type: 'junit', files: ['tests/data/junit/empty-suite.xml'] }); + assert.deepEqual(result, { + id: '', + name: 'result name', + total: 1, + passed: 0, + failed: 1, + errors: 0, + skipped: 0, + duration: 10000, + status: 'FAIL', + suites: [ + { + id: '', + name: 'suite name', + total: 1, + passed: 0, + failed: 1, + errors: 0, + skipped: 0, + duration: 10000, + status: 'FAIL', + cases: [] + } + ] + }); + }); + + it('suite with skipped tests', () => { + const result = parse({ type: 'junit', files: ['tests/data/junit/skipped-tests.xml'] }); + assert.deepEqual(result, { + id: '', + name: 'result name', + total: 1, + passed: 1, + failed: 0, + errors: 0, + skipped: 1, + duration: 10000, + status: 'PASS', + suites: [ + { + id: '', + name: 'suite name', + total: 1, + passed: 1, + failed: 0, + errors: 0, + skipped: 0, + duration: 10000, + status: 'PASS', + cases: [] + } + ] + }); + }); + + it('multiple suites', () => { + const result = parse({ type: 'junit', files: ['tests/data/junit/multiple-suites.xml'] }); + assert.deepEqual(result, { + id: '', + name: 'result name', + total: 2, + passed: 1, + failed: 1, + errors: 0, + skipped: 0, + duration: 20000, + status: 'FAIL', + suites: [ + { + id: '', + name: 'suite name 1', + total: 1, + passed: 0, + failed: 1, + errors: 0, + skipped: 0, + duration: 10000, + status: 'FAIL', + cases: [] + }, + { + id: '', + name: 'suite name 2', + total: 1, + passed: 1, + failed: 0, + errors: 0, + skipped: 0, + duration: 10000, + status: 'PASS', + cases: [] + } + ] + }); + }); + +}); \ No newline at end of file diff --git a/tests/parser.testng.spec.js b/tests/parser.testng.spec.js index 0e5a295..66b5203 100644 --- a/tests/parser.testng.spec.js +++ b/tests/parser.testng.spec.js @@ -29,7 +29,7 @@ describe('Parser - TestNG', () => { cases: [] } ] - }) + }); }); it('single suite with multiple tests', () => { @@ -70,7 +70,7 @@ describe('Parser - TestNG', () => { cases: [] } ] - }) + }); }); it('multiple suites with single test', () => { @@ -99,7 +99,7 @@ describe('Parser - TestNG', () => { cases: [] } ] - }) + }); }); it('multiple suites with multiple tests', () => { @@ -140,7 +140,7 @@ describe('Parser - TestNG', () => { cases: [] } ] - }) + }); }); }); \ No newline at end of file