Skip to content

Commit

Permalink
implementation for nunit test-results-reporter#4
Browse files Browse the repository at this point in the history
  • Loading branch information
bryanbcook committed Nov 11, 2023
1 parent a44248f commit 622e10d
Show file tree
Hide file tree
Showing 5 changed files with 470 additions and 1 deletion.
15 changes: 14 additions & 1 deletion src/helpers/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,26 @@ const FORCED_ARRAY_KEYS = [
"testng-results.suite.test",
"testng-results.suite.test.class",
"testng-results.suite.test.class.test-method",
"testng-results.suite.test.class.test-method.exception",
"testng-results.suite.test.class.test-method.exception"
];

const configured_parser = new XMLParser({
isArray: (name, jpath, isLeafNode, isAttribute) => {
if( FORCED_ARRAY_KEYS.indexOf(jpath) !== -1) {
return true;
}
// handle nunit deep hierarchy
else if (jpath.startsWith("test-results")) {
let parts = jpath.split(".");
switch(parts[parts.length - 1]) {
case "category":
case "property":
case "test-suite":
case "test-case":
return true;
default:
return false;
}
}
},
ignoreAttributes: false,
Expand Down
3 changes: 3 additions & 0 deletions src/parsers/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const testng = require('./testng');
const junit = require('./junit');
const nunit = require('./nunit');
const xunit = require('./xunit');
const mocha = require('./mocha');
const cucumber = require('./cucumber');
Expand Down Expand Up @@ -37,6 +38,8 @@ function getParser(type) {
return junit;
case 'xunit':
return xunit;
case 'nunit':
return nunit;
case 'mocha':
return mocha;
case 'cucumber':
Expand Down
150 changes: 150 additions & 0 deletions src/parsers/nunit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
const { getJsonFromXMLFile } = require('../helpers/helper');

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

const SUITE_TYPES_WITH_TESTCASES = [
"TestFixture",
"ParameterizedTest",
"GenericFixture"
]

const RESULTMAP = {
Success: "PASS",
Failure: "FAIL",
Ignored: "SKIP",
NotRunnable: "SKIP",
Error: "ERROR",
Inconclusive: "FAIL"
}

function populateMetaData(raw, map) {
if (raw.categories) {
let categories = raw.categories.category;
for (let i = 0; i < categories.length; i++) {
let categoryName = categories[i]["@_name"];
map.set(categoryName, "");

// create comma-delimited list of categories
if (map.has("Categories")) {
map.set("Categories", map.get("Categories").concat(",", categoryName));
} else {
map.set("Categories", categoryName);
}
}
}
if (raw.properties) {
let properties = raw.properties.property;
for (let i = 0; i < properties.length; i++) {
let property = properties[i];
map.set(property["@_name"], property["@_value"]);
}
}
}

function getTestCases(rawSuite, parent_meta) {
var cases = [];

let rawTestCases = rawSuite.results["test-case"];
if (rawTestCases) {
for (let i = 0; i < rawTestCases.length; i++) {
let rawCase = rawTestCases[i];
let testCase = new TestCase();
let result = rawCase["@_result"]
testCase.name = rawCase["@_name"];
testCase.duration = rawCase["@_time"] * 1000; // in milliseconds
testCase.status = RESULTMAP[result];
if (rawCase["@_executed"] == "False") {
testCase.status = "SKIP"; // exclude failures that weren't executed.
}
let errorDetails = rawCase.reason ?? rawCase.failure;
if (errorDetails !== undefined) {
testCase.setFailure(errorDetails.message);
if (errorDetails["stack-trace"]) {
testCase.stack_trace = errorDetails["stack-trace"]
}
}
// copy parent_meta data to test case
for( let kvp of parent_meta.entries()) {
testCase.meta_data.set(kvp[0], kvp[1]);
}
populateMetaData(rawCase, testCase.meta_data);

cases.push( testCase );
}
}

return cases;
}

function getTestSuites(rawSuites) {
var suites = [];

for(let i = 0; i < rawSuites.length; i++) {
let rawSuite = rawSuites[i];

if (rawSuite.results["test-suite"]) {
// handle nested test-suites
suites.push(...getTestSuites(rawSuite.results["test-suite"]));
} else if (SUITE_TYPES_WITH_TESTCASES.indexOf(rawSuite["@_type"]) !== -1) {

let suite = new TestSuite();
suite.duration = rawSuite["@_time"] * 1000; // in milliseconds
suite.status = RESULTMAP[rawSuite["@_result"]];

var meta_data = new Map();
populateMetaData(rawSuite, meta_data);
suite.cases.push(...getTestCases(rawSuite, meta_data));

// calculate totals
suite.total = suite.cases.length;
suite.passed = suite.cases.filter(i => i.status == "PASS").length;
suite.failed = suite.cases.filter(i => i.status == "FAIL").length;
suite.errors = suite.cases.filter(i => i.status == "ERROR").length;
suite.skipped = suite.cases.filter(i => i.status == "SKIP").length;

suites.push(suite);
}
}

return suites;
}


function getTestResult(json) {
const rawResult = json["test-results"];
const rawSuite = rawResult["test-suite"][0];

const result = new TestResult();
result.name = rawResult["@_name"];
result.duration = rawSuite["@_time"] * 1000; // in milliseconds
// test-results attributes related to totals
// total = executed=True
// errors = result="Error"
// failures = result="Failure"
// not-run = executed=False
// inconclusive = result="Inconclusive"
// ignored = result="Ignored"
// skipped = sample has zero?
// invalid = result="NotRunable"
result.total = rawResult["@_total"] + rawResult["@_not-run"]; // total executed and not executed
result.errors = rawResult["@_errors"];
result.failed = rawResult["@_failures"];
result.skipped = rawResult["@_not-run"]; // Ignored, NotRunnable
// assume inconclusive is neither a pass or failure to prevent religious wars, total's won't match as a result.
result.passed = rawResult["@_total"] - (result.errors + result.failed + rawResult["@_inconclusive"]);

result.suites.push(getTestSuites( [ rawSuite ]) );

return result;
}

function parse(file) {
const json = getJsonFromXMLFile(file);
return getTestResult(json);
}

module.exports = {
parse
}
190 changes: 190 additions & 0 deletions tests/data/nunit/sample.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!--This file represents the results of running a test suite-->
<test-results name="/home/charlie/Dev/NUnit/nunit-2.5/work/src/bin/Debug/tests/mock-assembly.dll" total="21" errors="1" failures="1" not-run="7" inconclusive="1" ignored="4" skipped="0" invalid="3" date="2010-10-18" time="13:23:35">
<environment nunit-version="2.5.8.0" clr-version="2.0.50727.1433" os-version="Unix 2.6.32.25" platform="Unix" cwd="/home/charlie/Dev/NUnit/nunit-2.5/work/src/bin/Debug" machine-name="cedar" user="charlie" user-domain="cedar" />
<culture-info current-culture="en-US" current-uiculture="en-US" />
<test-suite type="Assembly" name="/home/charlie/Dev/NUnit/nunit-2.5/work/src/bin/Debug/tests/mock-assembly.dll" executed="True" result="Failure" success="False" time="0.824" asserts="0">
<results>
<test-suite type="Namespace" name="NUnit" executed="True" result="Failure" success="False" time="0.807" asserts="0">
<results>
<test-suite type="Namespace" name="Tests" executed="True" result="Failure" success="False" time="0.803" asserts="0">
<results>
<test-suite type="Namespace" name="Assemblies" executed="True" result="Failure" success="False" time="0.606" asserts="0">
<results>
<test-suite type="TestFixture" name="MockTestFixture" description="Fake Test Fixture" executed="True" result="Failure" success="False" time="0.582" asserts="0">
<categories>
<category name="FixtureCategory" />
</categories>
<results>
<test-case name="NUnit.Tests.Assemblies.MockTestFixture.FailingTest" executed="True" result="Failure" success="False" time="0.013" asserts="0">
<failure>
<message><![CDATA[Intentional failure]]></message>
<stack-trace><![CDATA[at NUnit.Tests.Assemblies.MockTestFixture.FailingTest () [0x00000] in /home/charlie/Dev/NUnit/nunit-2.5/work/src/tests/mock-assembly/MockAssembly.cs:121
]]> </stack-trace>
</failure>
</test-case>
<test-case name="NUnit.Tests.Assemblies.MockTestFixture.InconclusiveTest" executed="True" result="Inconclusive" success="False" time="0.001" asserts="0">
<reason>
<message><![CDATA[No valid data]]></message>
</reason>
</test-case>
<test-case name="NUnit.Tests.Assemblies.MockTestFixture.MockTest1" description="Mock Test #1" executed="True" result="Success" success="True" time="0.000" asserts="0" />
<test-case name="NUnit.Tests.Assemblies.MockTestFixture.MockTest2" description="This is a really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really, really long description" executed="True" result="Success" success="True" time="0.000" asserts="0">
<categories>
<category name="MockCategory" />
</categories>
<properties>
<property name="Severity" value="Critical" />
</properties>
</test-case>
<test-case name="NUnit.Tests.Assemblies.MockTestFixture.MockTest3" executed="True" result="Success" success="True" time="0.001" asserts="0">
<categories>
<category name="AnotherCategory" />
<category name="MockCategory" />
</categories>
<reason>
<message><![CDATA[Succeeded!]]></message>
</reason>
</test-case>
<test-case name="NUnit.Tests.Assemblies.MockTestFixture.MockTest4" executed="False" result="Ignored">
<categories>
<category name="Foo" />
</categories>
<reason>
<message><![CDATA[ignoring this test method for now]]></message>
</reason>
</test-case>
<test-case name="NUnit.Tests.Assemblies.MockTestFixture.MockTest5" executed="False" result="NotRunnable">
<reason>
<message><![CDATA[Method is not public]]></message>
</reason>
</test-case>
<test-case name="NUnit.Tests.Assemblies.MockTestFixture.NotRunnableTest" executed="False" result="NotRunnable">
<reason>
<message><![CDATA[No arguments were provided]]></message>
</reason>
</test-case>
<test-case name="NUnit.Tests.Assemblies.MockTestFixture.TestWithException" executed="True" result="Error" success="False" time="0.001" asserts="0">
<failure>
<message><![CDATA[System.ApplicationException : Intentional Exception]]></message>
<stack-trace><![CDATA[at NUnit.Tests.Assemblies.MockTestFixture.TestWithException () [0x00000] in /home/charlie/Dev/NUnit/nunit-2.5/work/src/tests/mock-assembly/MockAssembly.cs:153
]]> </stack-trace>
</failure>
</test-case>
<test-case name="NUnit.Tests.Assemblies.MockTestFixture.TestWithManyProperties" executed="True" result="Success" success="True" time="0.000" asserts="0">
<properties>
<property name="Size" value="5" />
<property name="TargetMethod" value="SomeClassName" />
</properties>
</test-case>
</results>
</test-suite>
</results>
</test-suite>
<test-suite type="TestFixture" name="BadFixture" executed="False" result="NotRunnable">
<reason>
<message><![CDATA[No suitable constructor was found]]></message>
</reason>
<results>
<test-case name="NUnit.Tests.BadFixture.SomeTest" executed="False" result="NotRunnable">
<reason>
<message><![CDATA[No suitable constructor was found]]></message>
</reason>
</test-case>
</results>
</test-suite>
<test-suite type="TestFixture" name="FixtureWithTestCases" executed="True" result="Success" success="True" time="0.043" asserts="0">
<results>
<test-suite type="ParameterizedTest" name="GenericMethod" executed="True" result="Success" success="True" time="0.013" asserts="0">
<results>
<test-case name="NUnit.Tests.FixtureWithTestCases.GenericMethod&lt;Double&gt;(9.2d,11.7d)" executed="True" result="Success" success="True" time="0.007" asserts="1" />
<test-case name="NUnit.Tests.FixtureWithTestCases.GenericMethod&lt;Int32&gt;(2,4)" executed="True" result="Success" success="True" time="0.001" asserts="1" />
</results>
</test-suite>
<test-suite type="ParameterizedTest" name="MethodWithParameters" executed="True" result="Success" success="True" time="0.011" asserts="0">
<results>
<test-case name="NUnit.Tests.FixtureWithTestCases.MethodWithParameters(9,11)" executed="True" result="Success" success="True" time="0.003" asserts="1" />
<test-case name="NUnit.Tests.FixtureWithTestCases.MethodWithParameters(2,2)" executed="True" result="Success" success="True" time="0.000" asserts="1" />
</results>
</test-suite>
</results>
</test-suite>
<test-suite type="GenericFixture" name="GenericFixture&lt;T&gt;" executed="True" result="Success" success="True" time="0.012" asserts="0">
<results>
<test-suite type="TestFixture" name="GenericFixture&lt;Double&gt;(11.5d)" executed="True" result="Success" success="True" time="0.011" asserts="0">
<results>
<test-case name="NUnit.Tests.GenericFixture&lt;Double&gt;(11.5d).Test1" executed="True" result="Success" success="True" time="0.000" asserts="0" />
<test-case name="NUnit.Tests.GenericFixture&lt;Double&gt;(11.5d).Test2" executed="True" result="Success" success="True" time="0.000" asserts="0" />
</results>
</test-suite>
<test-suite type="TestFixture" name="GenericFixture&lt;Int32&gt;(5)" executed="True" result="Success" success="True" time="0.001" asserts="0">
<results>
<test-case name="NUnit.Tests.GenericFixture&lt;Int32&gt;(5).Test1" executed="True" result="Success" success="True" time="0.000" asserts="0" />
<test-case name="NUnit.Tests.GenericFixture&lt;Int32&gt;(5).Test2" executed="True" result="Success" success="True" time="0.000" asserts="0" />
</results>
</test-suite>
</results>
</test-suite>
<test-suite type="TestFixture" name="IgnoredFixture" executed="False" result="Ignored">
<reason>
<message><![CDATA[]]></message>
</reason>
<results>
<test-case name="NUnit.Tests.IgnoredFixture.Test1" executed="False" result="Ignored">
<reason>
<message><![CDATA[]]></message>
</reason>
</test-case>
<test-case name="NUnit.Tests.IgnoredFixture.Test2" executed="False" result="Ignored">
<reason>
<message><![CDATA[]]></message>
</reason>
</test-case>
<test-case name="NUnit.Tests.IgnoredFixture.Test3" executed="False" result="Ignored">
<reason>
<message><![CDATA[]]></message>
</reason>
</test-case>
</results>
</test-suite>
<test-suite type="ParameterizedFixture" name="ParameterizedFixture" executed="True" result="Success" success="True" time="0.069" asserts="0">
<results>
<test-suite type="TestFixture" name="ParameterizedFixture(42)" executed="True" result="Success" success="True" time="0.048" asserts="0">
<results>
<test-case name="NUnit.Tests.ParameterizedFixture(42).Test1" executed="True" result="Success" success="True" time="0.000" asserts="0" />
<test-case name="NUnit.Tests.ParameterizedFixture(42).Test2" executed="True" result="Success" success="True" time="0.000" asserts="0" />
</results>
</test-suite>
<test-suite type="TestFixture" name="ParameterizedFixture(5)" executed="True" result="Success" success="True" time="0.007" asserts="0">
<results>
<test-case name="NUnit.Tests.ParameterizedFixture(5).Test1" executed="True" result="Success" success="True" time="0.000" asserts="0" />
<test-case name="NUnit.Tests.ParameterizedFixture(5).Test2" executed="True" result="Success" success="True" time="0.000" asserts="0" />
</results>
</test-suite>
</results>
</test-suite>
<test-suite type="Namespace" name="Singletons" executed="True" result="Success" success="True" time="0.005" asserts="0">
<results>
<test-suite type="TestFixture" name="OneTestCase" executed="True" result="Success" success="True" time="0.001" asserts="0">
<results>
<test-case name="NUnit.Tests.Singletons.OneTestCase.TestCase" executed="True" result="Success" success="True" time="0.000" asserts="0" />
</results>
</test-suite>
</results>
</test-suite>
<test-suite type="Namespace" name="TestAssembly" executed="True" result="Success" success="True" time="0.005" asserts="0">
<results>
<test-suite type="TestFixture" name="MockTestFixture" executed="True" result="Success" success="True" time="0.001" asserts="0">
<results>
<test-case name="NUnit.Tests.TestAssembly.MockTestFixture.MyTest" executed="True" result="Success" success="True" time="0.000" asserts="0" />
</results>
</test-suite>
</results>
</test-suite>
</results>
</test-suite>
</results>
</test-suite>
</results>
</test-suite>
</test-results>
Loading

0 comments on commit 622e10d

Please sign in to comment.