Skip to content

Commit d3fdae9

Browse files
authored
Merge pull request #12 from test-results-reporter/feature/support-cucumberjs-json-parser
Add cucumberjs json report parser
2 parents ac9d105 + de2d182 commit d3fdae9

File tree

8 files changed

+507
-3
lines changed

8 files changed

+507
-3
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,5 @@ dist
103103
# TernJS port file
104104
.tern-port
105105

106-
.DS_Store
106+
.DS_Store
107+
.vscode

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# test-results-parser
22

3-
Parse test results from JUnit, TestNG, xUnit, Mocha and many more
3+
Parse test results from JUnit, TestNG, xUnit, Mocha(json), Cucumber(json) and many more
44

55
## Support
66

@@ -9,4 +9,5 @@ Parse test results from JUnit, TestNG, xUnit, Mocha and many more
99
| TestNG ||
1010
| JUnit ||
1111
| xUnit ||
12-
| Mocha (json & mochawesome) ||
12+
| Mocha (json & mochawesome) ||
13+
| Cucumber ||

src/parsers/cucumber.js

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Parser for both Mocha Json report and Mochawesome json
3+
*/
4+
const path = require('path');
5+
6+
const TestResult = require('../models/TestResult');
7+
const TestSuite = require('../models/TestSuite');
8+
const TestCase = require('../models/TestCase');
9+
10+
function getTestCase(rawCase) {
11+
const test_case = new TestCase();
12+
test_case.name = rawCase["name"];
13+
test_case.duration = rawCase["duration"];
14+
if (rawCase.state && rawCase.state === "failed") {
15+
test_case.status = 'FAIL';
16+
test_case.failure = rawCase.errorStack;
17+
}
18+
else {
19+
test_case.status = 'PASS';
20+
}
21+
return test_case;
22+
}
23+
24+
function getTestSuite(rawSuite) {
25+
const suite = new TestSuite();
26+
suite.name = rawSuite["name"];
27+
suite.total = rawSuite["tests"];
28+
suite.passed = rawSuite["passes"];
29+
suite.failed = rawSuite["failures"];
30+
suite.duration = rawSuite["duration"];
31+
suite.status = suite.total === suite.passed ? 'PASS' : 'FAIL';
32+
const raw_test_cases = rawSuite.elements;
33+
if (raw_test_cases) {
34+
for (let i = 0; i < raw_test_cases.length; i++) {
35+
suite.cases.push(getTestCase(raw_test_cases[i]));
36+
}
37+
}
38+
return suite;
39+
}
40+
41+
function getTestResult(json) {
42+
const result = new TestResult();
43+
const { stats, suites } = preprocess(json);
44+
result.name = suites["name"] || "";
45+
result.total = stats["tests"];
46+
result.passed = stats["passes"];
47+
result.failed = stats["failures"];
48+
const errors = stats["errors"];
49+
if (errors) {
50+
result.errors = errors;
51+
}
52+
result.duration = stats["duration"] || 0;
53+
54+
if (suites.length > 0) {
55+
for (let i = 0; i < suites.length; i++) {
56+
result.suites.push(getTestSuite(suites[i]));
57+
}
58+
}
59+
result.status = result.total === result.passed ? 'PASS' : 'FAIL';
60+
return result;
61+
}
62+
63+
/**
64+
* Function to format the raw json report
65+
* @param {*} rawjson
66+
* @returns formatted json object
67+
*/
68+
function preprocess(rawjson) {
69+
const formattedResult = { stats: {}, suites: [] };
70+
71+
rawjson.forEach(testSuite => {
72+
testSuite.elements.forEach(testCase => {
73+
testCase.state = testCase.steps.every(step => step.result.status === "passed") ? "passed" : "failed";
74+
testCase.duration = testCase.steps.map(step => step.result.duration).reduce((total, currVal) => total + currVal, 0) / 1000000;
75+
testCase.duration = parseFloat(testCase.duration.toFixed(2));
76+
testCase.errorStack = testCase.steps.filter(step => step.result.status === "failed").map(step => step.result.error_message)[0] || "";
77+
})
78+
testSuite.tests = testSuite.elements.length;
79+
80+
if (testSuite.tests) {
81+
testSuite.failures = testSuite.elements.filter(testCase => testCase.state === "failed").length;
82+
testSuite.passes = testSuite.elements.filter(testCase => testCase.state === "passed").length;
83+
testSuite.duration = testSuite.elements.map(testCase => testCase.duration).reduce((total, currVal) => total + currVal, 0);
84+
}
85+
formattedResult.suites.push(testSuite);
86+
});
87+
88+
formattedResult.stats.suites = formattedResult.suites.length;
89+
for (const statsType of ["tests", "passes", "failures", "errors", "duration"]) {
90+
formattedResult.stats[statsType] = formattedResult.suites.map(testSuite => testSuite[statsType]).reduce((total, currVal) => total + currVal, 0) || 0;
91+
}
92+
return formattedResult;
93+
}
94+
95+
function parse(options) {
96+
const cwd = process.cwd();
97+
const json = require(path.join(cwd, options.files[0]));
98+
return getTestResult(json);
99+
}
100+
101+
module.exports = {
102+
parse
103+
}

src/parsers/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const testng = require('./testng');
22
const junit = require('./junit');
33
const xunit = require('./xunit');
44
const mocha = require('./mocha');
5+
const cucumber = require('./cucumber');
56

67
function parse(options) {
78
switch (options.type) {
@@ -13,6 +14,8 @@ function parse(options) {
1314
return xunit.parse(options);
1415
case 'mocha':
1516
return mocha.parse(options);
17+
case 'cucumber':
18+
return cucumber.parse(options);
1619
default:
1720
throw `UnSupported Result Type - ${options.type}`;
1821
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
[
2+
{
3+
"description": " Verify calculator functionalities",
4+
"elements": [
5+
{
6+
"description": "",
7+
"id": "addition;addition-of-two-numbers",
8+
"keyword": "Scenario",
9+
"line": 4,
10+
"name": "Addition of two numbers",
11+
"steps": [
12+
{
13+
"arguments": [],
14+
"keyword": "Given ",
15+
"line": 5,
16+
"name": "I have number 6 in calculator",
17+
"match": {
18+
"location": "features\\support\\steps.js:5"
19+
},
20+
"result": {
21+
"status": "passed",
22+
"duration": 1098599
23+
}
24+
},
25+
{
26+
"arguments": [],
27+
"keyword": "When ",
28+
"line": 6,
29+
"name": "I add number 7",
30+
"match": {
31+
"location": "features\\support\\steps.js:9"
32+
},
33+
"result": {
34+
"status": "passed",
35+
"duration": 132100
36+
}
37+
},
38+
{
39+
"arguments": [],
40+
"keyword": "Then ",
41+
"line": 7,
42+
"name": "I should see result 14",
43+
"match": {
44+
"location": "features\\support\\steps.js:17"
45+
},
46+
"result": {
47+
"status": "failed",
48+
"duration": 1330499,
49+
"error_message": "AssertionError [ERR_ASSERTION]: 13 == 14\n + expected - actual\n\n -13\n +14\n\n at CustomWorld.<anonymous> (D:\\workspace\\nodejs\\cc-tests\\features\\support\\steps.js:18:12)"
50+
}
51+
}
52+
],
53+
"tags": [],
54+
"type": "scenario"
55+
},
56+
{
57+
"description": "",
58+
"id": "addition;addition-of-two-numbers-v2",
59+
"keyword": "Scenario",
60+
"line": 9,
61+
"name": "Addition of two numbers v2",
62+
"steps": [
63+
{
64+
"arguments": [],
65+
"keyword": "Given ",
66+
"line": 10,
67+
"name": "I have number 6 in calculator",
68+
"match": {
69+
"location": "features\\support\\steps.js:5"
70+
},
71+
"result": {
72+
"status": "passed",
73+
"duration": 110200
74+
}
75+
},
76+
{
77+
"arguments": [],
78+
"keyword": "When ",
79+
"line": 11,
80+
"name": "I add number 7",
81+
"match": {
82+
"location": "features\\support\\steps.js:9"
83+
},
84+
"result": {
85+
"status": "passed",
86+
"duration": 97300
87+
}
88+
},
89+
{
90+
"arguments": [],
91+
"keyword": "Then ",
92+
"line": 12,
93+
"name": "I should see result 13",
94+
"match": {
95+
"location": "features\\support\\steps.js:17"
96+
},
97+
"result": {
98+
"status": "passed",
99+
"duration": 76900
100+
}
101+
}
102+
],
103+
"tags": [],
104+
"type": "scenario"
105+
}
106+
],
107+
"id": "addition",
108+
"line": 1,
109+
"keyword": "Feature",
110+
"name": "Addition",
111+
"tags": [],
112+
"uri": "features\\addition.feature"
113+
},
114+
{
115+
"description": " Verify calculator functionalities",
116+
"elements": [
117+
{
118+
"description": "",
119+
"id": "subtraction;subtraction-of-two-numbers",
120+
"keyword": "Scenario",
121+
"line": 4,
122+
"name": "Subtraction of two numbers",
123+
"steps": [
124+
{
125+
"arguments": [],
126+
"keyword": "Given ",
127+
"line": 5,
128+
"name": "I have number 10 in calculator",
129+
"match": {
130+
"location": "features\\support\\steps.js:5"
131+
},
132+
"result": {
133+
"status": "passed",
134+
"duration": 79800
135+
}
136+
},
137+
{
138+
"arguments": [],
139+
"keyword": "When ",
140+
"line": 6,
141+
"name": "I subtract number 7",
142+
"match": {
143+
"location": "features\\support\\steps.js:13"
144+
},
145+
"result": {
146+
"status": "passed",
147+
"duration": 134299
148+
}
149+
},
150+
{
151+
"arguments": [],
152+
"keyword": "Then ",
153+
"line": 7,
154+
"name": "I should see result 3",
155+
"match": {
156+
"location": "features\\support\\steps.js:17"
157+
},
158+
"result": {
159+
"status": "passed",
160+
"duration": 309700
161+
}
162+
}
163+
],
164+
"tags": [],
165+
"type": "scenario"
166+
}
167+
],
168+
"id": "subtraction",
169+
"line": 1,
170+
"keyword": "Feature",
171+
"name": "Subtraction",
172+
"tags": [],
173+
"uri": "features\\subtract.feature"
174+
}
175+
]
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
[
2+
{
3+
"description": "Verify calculator functionalities",
4+
"elements": [
5+
{
6+
"description": "",
7+
"id": "addition;addition-of-two-numbers",
8+
"keyword": "Scenario",
9+
"line": 5,
10+
"name": "Addition of two numbers",
11+
"steps": [
12+
{
13+
"arguments": [],
14+
"keyword": "Given ",
15+
"line": 6,
16+
"name": "I have number 6 in calculator",
17+
"match": {
18+
"location": "features\\support\\steps.js:5"
19+
},
20+
"result": {
21+
"status": "passed",
22+
"duration": 1211400
23+
}
24+
},
25+
{
26+
"arguments": [],
27+
"keyword": "When ",
28+
"line": 7,
29+
"name": "I entered number 7",
30+
"match": {
31+
"location": "features\\support\\steps.js:9"
32+
},
33+
"result": {
34+
"status": "passed",
35+
"duration": 136500
36+
}
37+
},
38+
{
39+
"arguments": [],
40+
"keyword": "Then ",
41+
"line": 8,
42+
"name": "I should see result 13",
43+
"match": {
44+
"location": "features\\support\\steps.js:13"
45+
},
46+
"result": {
47+
"status": "passed",
48+
"duration": 244700
49+
}
50+
}
51+
],
52+
"tags": [
53+
{
54+
"name": "@green",
55+
"line": 4
56+
}
57+
],
58+
"type": "scenario"
59+
}
60+
],
61+
"id": "addition",
62+
"line": 1,
63+
"keyword": "Feature",
64+
"name": "Addition",
65+
"tags": [],
66+
"uri": "features\\sample.feature"
67+
}
68+
]

0 commit comments

Comments
 (0)