Skip to content

Commit

Permalink
Merge pull request #10 from test-results-reporter/feature/add-mocha-r…
Browse files Browse the repository at this point in the history
…eport-parser

Feature/add mocha report parser
  • Loading branch information
leelaprasadv authored Jun 11, 2022
2 parents 52eb962 + cda7935 commit 7ea2543
Show file tree
Hide file tree
Showing 12 changed files with 1,158 additions and 6 deletions.
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# test-results-parser

Parse test results from JUnit, TestNG, xUnit and many more
Parse test results from JUnit, TestNG, xUnit, Mocha and many more

## Support

| Result Type | Support |
|-------------|---------|
| TestNG ||
| JUnit ||
| xUnit ||
| Result Type | Support |
|-------------------------------|---------|
| TestNG ||
| JUnit ||
| xUnit ||
| Mocha (json & mochawesome) ||
3 changes: 3 additions & 0 deletions src/parsers/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const testng = require('./testng');
const junit = require('./junit');
const xunit = require('./xunit');
const mocha = require('./mocha');

function parse(options) {
switch (options.type) {
Expand All @@ -10,6 +11,8 @@ function parse(options) {
return junit.parse(options);
case 'xunit':
return xunit.parse(options);
case 'mocha':
return mocha.parse(options);
default:
throw `UnSupported Result Type - ${options.type}`;
}
Expand Down
119 changes: 119 additions & 0 deletions src/parsers/mocha.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* Parser for both Mocha Json report and Mochawesome json
*/
const path = require('path');

const TestResult = require('../models/TestResult');
const TestSuite = require('../models/TestSuite');
const TestCase = require('../models/TestCase');

function getTestCase(rawCase) {
const test_case = new TestCase();
test_case.name = rawCase["title"];
test_case.duration = rawCase["duration"] * 1000;
if (rawCase["state"] == "pending") {
test_case.status = 'SKIP';
}
else if (rawCase.state && rawCase.state === "failed") {
test_case.status = 'FAIL';
test_case.failure = rawCase.err["message"];
}
else {
test_case.status = 'PASS';
}
return test_case;
}

function getTestSuite(rawSuite) {
const suite = new TestSuite();
suite.name = rawSuite["title"];
suite.total = rawSuite["tests"].length;
suite.passed = rawSuite["passes"].length;
suite.failed = rawSuite["failures"].length;
suite.duration = rawSuite["duration"] * 1000;
suite.skipped = rawSuite["pending"].length;
suite.status = suite.total === (suite.passed + suite.skipped) ? 'PASS' : 'FAIL';
const raw_test_cases = rawSuite.tests;
if (raw_test_cases) {
for (let i = 0; i < raw_test_cases.length; i++) {
suite.cases.push(getTestCase(raw_test_cases[i]));
}
}
return suite;
}

function getTestResult(json) {
const result = new TestResult();
const { stats, results } = formatMochaJsonReport(json);
const formattedResult = results[0] || {};
const suites = formattedResult["suites"] || [];

result.name = formattedResult["title"] || "";
result.total = stats["tests"];
result.passed = stats["passes"];
result.failed = stats["failures"];
const errors = formattedResult["errors"];
if (errors) {
result.errors = errors;
}
const skipped = stats["pending"];
if (skipped) {
result.skipped = skipped;
}
result.duration = (stats["duration"] || 0) * 1000;

if (suites.length > 0) {
for (let i = 0; i < suites.length; i++) {
result.suites.push(getTestSuite(suites[i]));
}
}
result.status = (result.total - result.skipped) === result.passed ? 'PASS' : 'FAIL';
return result;
}

/**
* Function to format the mocha raw json report
* @param {*} rawjson
* @returns formatted json object
*/
function formatMochaJsonReport(rawjson) {
if (rawjson.hasOwnProperty('meta')) {
return rawjson
}
const formattedJson = { stats: rawjson.stats, results: [] };
const suites = [];
rawjson.failures.forEach(test => test.state = "failed");
rawjson.passes.forEach(test => test.state = "passed");
rawjson.pending.forEach( test => {
test.state = "pending";
test.duration = 0;
});

const rawTests = [...rawjson.passes, ...rawjson.failures, ...rawjson.pending];
const testSuites = [...new Set(rawTests.map(test => test.fullTitle.split(' ' + test.title)[0]))];

for (const testSuite of testSuites) {
const suite = {
title: testSuite,
tests: rawTests.filter(test => test.fullTitle.startsWith(testSuite))
}
suite.passes = suite.tests.filter(test => test.state === "passed");
suite.failures = suite.tests.filter(test => test.state === "failed");
suite.pending = suite.tests.filter(test => test.state === "pending");
suite.duration = suite.tests.map(test => test.duration).reduce((total, currVal) => total + currVal, 0);
suite.fullFile = suite.tests[0].file || "";
suites.push(suite);
}
formattedJson.results.push({ suites: suites });
return formattedJson;
}

function parse(options) {
const cwd = process.cwd();
const json = require(path.join(cwd, options.files[0]));
return getTestResult(json);
}

module.exports = {
parse
}
43 changes: 43 additions & 0 deletions tests/data/mocha/awesome/empty-suite.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"stats": {
"suites": 0,
"tests": 0,
"passes": 0,
"pending": 0,
"failures": 0,
"start": "2022-06-11T05:20:39.076Z",
"end": "2022-06-11T05:20:39.077Z",
"duration": 0,
"testsRegistered": 0,
"passPercent": null,
"pendingPercent": null,
"other": 0,
"hasOther": false,
"skipped": 0,
"hasSkipped": false
},
"results": [
false
],
"meta": {
"mocha": {
"version": "10.0.0"
},
"mochawesome": {
"options": {
"quiet": false,
"reportFilename": "mochawesome",
"saveHtml": true,
"saveJson": true,
"consoleReporter": "spec",
"useInlineDiffs": false,
"code": true
},
"version": "7.1.3"
},
"marge": {
"options": null,
"version": "6.2.0"
}
}
}
162 changes: 162 additions & 0 deletions tests/data/mocha/awesome/multiple-suites-multiple-tests.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
{
"stats": {
"suites": 2,
"tests": 3,
"passes": 2,
"pending": 0,
"failures": 1,
"start": "2022-06-11T05:28:11.204Z",
"end": "2022-06-11T05:28:11.227Z",
"duration": 7,
"testsRegistered": 3,
"passPercent": 63.333,
"pendingPercent": 0,
"other": 0,
"hasOther": false,
"skipped": 0,
"hasSkipped": false
},
"results": [
{
"uuid": "c3036d47-45a3-4c59-a114-fc90f4ad0532",
"title": "",
"fullFile": "",
"file": "",
"beforeHooks": [],
"afterHooks": [],
"tests": [],
"suites": [
{
"uuid": "544d6fcc-7849-4a32-aff8-b0be8e076fae",
"title": "Example Suite 1",
"fullFile": "",
"file": "",
"beforeHooks": [],
"afterHooks": [],
"tests": [
{
"title": "sample test case",
"fullTitle": "Example Suite 1 sample test case",
"timedOut": false,
"duration": 3,
"state": "passed",
"speed": "fast",
"pass": true,
"fail": false,
"pending": false,
"context": null,
"code": "",
"err": {},
"uuid": "47fa7bb9-a77f-43b3-abd0-59e2afa0ef0e",
"parentUUID": "544d6fcc-7849-4a32-aff8-b0be8e076fae",
"isHook": false,
"skipped": false
},
{
"title": "sample test case 2",
"fullTitle": "Example Suite 1 sample test case 2",
"timedOut": false,
"duration": 1,
"state": "passed",
"speed": "fast",
"pass": true,
"fail": false,
"pending": false,
"context": null,
"code": "",
"err": {},
"uuid": "14a946f8-b19e-43db-bc31-d75337ab55b3",
"parentUUID": "544d6fcc-7849-4a32-aff8-b0be8e076fae",
"isHook": false,
"skipped": false
}
],
"suites": [],
"passes": [
"47fa7bb9-a77f-43b3-abd0-59e2afa0ef0e",
"14a946f8-b19e-43db-bc31-d75337ab55b3"
],
"failures": [],
"pending": [],
"skipped": [],
"duration": 4,
"root": false,
"rootEmpty": false,
"_timeout": 2000
},
{
"uuid": "2fc0097a-29a4-4cc0-b045-007da8367164",
"title": "Example Suite 2",
"fullFile": "",
"file": "",
"beforeHooks": [],
"afterHooks": [],
"tests": [
{
"title": "sample test case",
"fullTitle": "Example Suite 2 sample test case",
"timedOut": false,
"duration": 1,
"state": "failed",
"speed": null,
"pass": false,
"fail": true,
"pending": false,
"context": null,
"code": "",
"err": {
"message": "Dummy reason",
"estack": "AssertionError [ERR_ASSERTION]: Dummy reason\n at Context.<anonymous> (tests\\parser.mocha.json.spec.js:7:12)\n at processImmediate (node:internal/timers:466:21)",
"diff": null
},
"uuid": "6bcc8efe-94ba-45c9-85cd-2cbe5ba777b1",
"parentUUID": "2fc0097a-29a4-4cc0-b045-007da8367164",
"isHook": false,
"skipped": false
}
],
"suites": [],
"passes": [],
"failures": [
"6bcc8efe-94ba-45c9-85cd-2cbe5ba777b1"
],
"pending": [],
"skipped": [],
"duration": 1,
"root": false,
"rootEmpty": false,
"_timeout": 2000
}
],
"passes": [],
"failures": [],
"pending": [],
"skipped": [],
"duration": 0,
"root": true,
"rootEmpty": true,
"_timeout": 2000
}
],
"meta": {
"mocha": {
"version": "10.0.0"
},
"mochawesome": {
"options": {
"quiet": false,
"reportFilename": "mochawesome",
"saveHtml": true,
"saveJson": true,
"consoleReporter": "spec",
"useInlineDiffs": false,
"code": true
},
"version": "7.1.3"
},
"marge": {
"options": null,
"version": "6.2.0"
}
}
}
Loading

0 comments on commit 7ea2543

Please sign in to comment.