From aef028c8c0d3bceb6dec6aefbbb2fb43d4738b80 Mon Sep 17 00:00:00 2001 From: Anudeep Date: Wed, 17 Apr 2024 18:57:05 +0530 Subject: [PATCH] Junit stack trace from failure (#62) * fetch stack trace * chore: rename ignore_errors to error_count --- package-lock.json | 4 +- package.json | 2 +- src/index.d.ts | 2 +- src/parsers/junit.js | 31 ++-- .../junit/mocha-failures-with-stack-trace.xml | 167 ++++++++++++++++++ tests/parser.junit.spec.js | 117 ++---------- 6 files changed, 210 insertions(+), 113 deletions(-) create mode 100644 tests/data/junit/mocha-failures-with-stack-trace.xml diff --git a/package-lock.json b/package-lock.json index 7cb31e3..69c29c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "test-results-parser", - "version": "0.1.13", + "version": "0.1.14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "test-results-parser", - "version": "0.1.13", + "version": "0.1.14", "license": "MIT", "dependencies": { "fast-xml-parser": "^4.3.2", diff --git a/package.json b/package.json index 4b6b595..18ba71d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "test-results-parser", - "version": "0.1.13", + "version": "0.1.14", "description": "Parse test results from JUnit, TestNG, xUnit, cucumber and many more", "main": "src/index.js", "types": "./src/index.d.ts", diff --git a/src/index.d.ts b/src/index.d.ts index fcfc07e..5164da7 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -2,7 +2,7 @@ import TestResult from "./models/TestResult"; declare interface ParseOptions { type: string; - ignore_errors?: boolean; + ignore_error_count?: boolean; files: string[]; } diff --git a/src/parsers/junit.js b/src/parsers/junit.js index 8059d8c..7d95dff 100644 --- a/src/parsers/junit.js +++ b/src/parsers/junit.js @@ -14,20 +14,29 @@ function getTestCase(rawCase, suite_meta) { setMetaData(rawCase, test_case); if (rawCase.failure && rawCase.failure.length > 0) { test_case.status = 'FAIL'; - test_case.setFailure(rawCase.failure[0]["@_message"]); - // wdio junit reporter - if (!test_case.failure && rawCase.error && rawCase.error.length > 0) { - test_case.setFailure(rawCase.error[0]["@_message"]); - } - if (rawCase['system-err'] && rawCase['system-err'].length > 0) { - test_case.stack_trace = rawCase['system-err'][0]; - } + set_error_and_stack_trace(test_case, rawCase); } else { test_case.status = 'PASS'; } return test_case; } +function set_error_and_stack_trace(test_case, raw_case) { + test_case.setFailure(raw_case.failure[0]["@_message"]); + // wdio junit reporter + if (!test_case.failure && raw_case.error && raw_case.error.length > 0) { + test_case.setFailure(raw_case.error[0]["@_message"]); + } + if (raw_case['system-err'] && raw_case['system-err'].length > 0) { + test_case.stack_trace = raw_case['system-err'][0]; + } + if (!test_case.stack_trace) { + if (raw_case.failure[0]["#text"]) { + test_case.stack_trace = raw_case.failure[0]["#text"]; + } + } +} + /** * * @param {object} rawSuite @@ -40,7 +49,7 @@ function getTestSuite(rawSuite, options) { suite.total = rawSuite["@_tests"]; suite.failed = rawSuite["@_failures"]; const errors = rawSuite["@_errors"]; - if (!options.ignore_errors && errors) { + if (!options.ignore_error_count && errors) { suite.errors = errors; } const skipped = rawSuite["@_skipped"]; @@ -68,7 +77,7 @@ function getTestSuite(rawSuite, options) { function setMetaData(rawElement, test_element) { if (rawElement.properties && rawElement.properties.property.length > 0) { const raw_properties = rawElement.properties.property; - for (const raw_property of raw_properties) { + for (const raw_property of raw_properties) { test_element.meta_data.set(raw_property["@_name"], raw_property["@_value"]); } } @@ -153,7 +162,7 @@ function getTestResult(json, options) { result.total = rawResult["@_tests"]; result.failed = rawResult["@_failures"]; const errors = rawResult["@_errors"]; - if (!options.ignore_errors && errors) { + if (!options.ignore_error_count && errors) { result.errors = errors; } const skipped = rawResult["@_skipped"]; diff --git a/tests/data/junit/mocha-failures-with-stack-trace.xml b/tests/data/junit/mocha-failures-with-stack-trace.xml new file mode 100644 index 0000000..0f36c4d --- /dev/null +++ b/tests/data/junit/mocha-failures-with-stack-trace.xml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/tests/parser.junit.spec.js b/tests/parser.junit.spec.js index efe8f6a..05cb811 100644 --- a/tests/parser.junit.spec.js +++ b/tests/parser.junit.spec.js @@ -42,7 +42,7 @@ describe('Parser - JUnit', () => { name: "Use a program name that matches the source file name", passed: 0, skipped: 0, - stack_trace: "", + stack_trace: "Some Text", status: "FAIL", meta_data: new Map(), steps: [], @@ -186,7 +186,7 @@ describe('Parser - JUnit', () => { name: "Use a program name that matches the source file name", passed: 0, skipped: 0, - stack_trace: "", + stack_trace: "Some Text", status: "FAIL", meta_data: new Map(), steps: [], @@ -216,7 +216,7 @@ describe('Parser - JUnit', () => { name: "Use a program name that matches the source file name", passed: 0, skipped: 0, - stack_trace: "", + stack_trace: "Some Text", status: "FAIL", meta_data: new Map(), steps: [], @@ -264,7 +264,7 @@ describe('Parser - JUnit', () => { name: "Use a program name that matches the source file name", passed: 0, skipped: 0, - stack_trace: "", + stack_trace: "Some Text", status: "FAIL", meta_data: new Map(), steps: [], @@ -294,7 +294,7 @@ describe('Parser - JUnit', () => { name: "Use a program name that matches the source file name", passed: 0, skipped: 0, - stack_trace: "", + stack_trace: "Some Text", status: "FAIL", meta_data: new Map(), steps: [], @@ -451,98 +451,8 @@ describe('Parser - JUnit', () => { it('parse spekt/junit.testlogger', () => { const result = parse({ type: 'junit', files: [`${testDataPath}/junit.testlogger.xml`] }); var inheritedProperties = new Map([["hostname", "REDACTED"]]); - assert.deepEqual(result, { - id: "", - name: "", - total: 3, - passed: 2, - failed: 1, - errors: 0, - skipped: 1, - retried: 0, - duration: 870.6800000000001, - status: "FAIL", - suites: [ - { - id: "", - name: "JUnit.Xml.TestLogger.NetCore.Tests.dll", - total: 3, - passed: 2, - failed: 1, - errors: 0, - skipped: 1, - duration: 870.6800000000001, - status: "FAIL", - meta_data: inheritedProperties, - cases: [ - { - id: "", - name: "TestD", - total: 0, - passed: 0, - failed: 0, - errors: 0, - skipped: 0, - duration: 2.195, - status: "PASS", - failure: "", - stack_trace: "", - meta_data: inheritedProperties, - attachments: [], - steps: [] - }, - { - id: "", - name: "TestC", - total: 0, - passed: 0, - failed: 0, - errors: 0, - skipped: 0, - duration: 1.109, - status: "FAIL", - failure: "TearDown : System.InvalidOperationException : Operation is not valid due to the current state of the object.", - stack_trace: "", - meta_data: inheritedProperties, - attachments: [], - steps: [] - }, - { - id: "", - name: "InconclusiveTest", - total: 0, - passed: 0, - failed: 0, - errors: 0, - skipped: 0, - duration: 0.7200000000000001, - status: "PASS", - failure: "", - stack_trace: "", - meta_data: inheritedProperties, - attachments: [], - steps: [] - }, - { - id: "", - name: "Ignored", - total: 0, - passed: 0, - failed: 0, - errors: 0, - skipped: 0, - duration: 0.29500000000000004, - status: "PASS", - failure: "", - stack_trace: "", - meta_data: inheritedProperties, - attachments: [], - steps: [] - } - ] - } - ] - }); + assert.deepEqual(result.suites[0].meta_data, inheritedProperties); + assert.deepEqual(result.suites[0].cases[0].meta_data, inheritedProperties); }); it('parse testcafe with testsuite root node', () => { @@ -648,7 +558,7 @@ describe('Parser - JUnit', () => { }); it('wdio - failures and ignore errors', () => { - const result = parse({ type: 'junit', ignore_errors: true, files: [`${testDataPath}/wdio-failures-errors.xml`] }); + const result = parse({ type: 'junit', ignore_error_count: true, files: [`${testDataPath}/wdio-failures-errors.xml`] }); assert.equal(result.total, 4); assert.equal(result.passed, 2); assert.equal(result.failed, 2); @@ -661,4 +571,15 @@ describe('Parser - JUnit', () => { assert.match(result.suites[0].cases[1].stack_trace, /middlewares.js:18:32/); }); + it('mocha - failures with stack trace', () => { + const result = parse({ type: 'junit', ignore_error_count: true, files: [`${testDataPath}/mocha-failures-with-stack-trace.xml`] }); + assert.equal(result.total, 51); + assert.equal(result.passed, 49); + assert.equal(result.failed, 2); + assert.equal(result.errors, 0); + assert.equal(result.status, 'FAIL'); + assert.equal(result.suites[5].cases[0].failure, `HTTP status 200 !== 400`); + assert.match(result.suites[5].cases[0].stack_trace, /at Expect._validateStatus/); + }) + }); \ No newline at end of file