From 4e6efe91a5fa390da56708e11af34b54f7ce784d Mon Sep 17 00:00:00 2001 From: Justin SB Date: Tue, 29 Jul 2014 09:44:50 -0700 Subject: [PATCH] Output test results in xunit format when the path is 'xunit' We output via console.log; to differentiate from normal output, we prefix xunit output with 'XUNIT '. --- packages/test-in-console/driver.js | 72 +++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/packages/test-in-console/driver.js b/packages/test-in-console/driver.js index 50e03156f3..35208a0b74 100644 --- a/packages/test-in-console/driver.js +++ b/packages/test-in-console/driver.js @@ -8,18 +8,43 @@ TEST_STATUS = { FAILURES: null }; +// xUnit format uses XML output +var XML_CHAR_MAP = { + '<': '<', + '>': '>', + '&': '&', + '"': '"', + "'": ''' +}; +// Escapes a string for insertion into XML +var escapeXml = function (s) { + return s.replace(/[<>&"']/g, function (c) { + return XML_CHAR_MAP[c]; + }); +} + +// Returns a human name for a test var getName = function (result) { return (result.server ? "S: " : "C: ") + result.groupPath.join(" - ") + " - " + result.test; }; +// Calls console.log, but returns silently if console.log is not available var log = function (/*arguments*/) { if (typeof console !== 'undefined') { console.log.apply(console, arguments); } }; +// Logs xUnit output, if xunit output is enabled +// Output is sent to console.log, prefixed with a magic string 'XUNIT ' +// By grepping for that prefix, the xUnit output can be extracted +var xunit = function (s) { + if (xunitEnabled) { + log('XUNIT ' + s); + } +}; var passed = 0; var failed = 0; @@ -31,6 +56,10 @@ var hrefPath = document.location.href.split("/"); var platform = decodeURIComponent(hrefPath.length && hrefPath[hrefPath.length - 1]); if (!platform) platform = "local"; + +// We enable xUnit output when platform is xunit +var xunitEnabled = (platform == 'xunit'); + var doReport = Meteor && Meteor.settings && Meteor.settings.public && @@ -82,10 +111,13 @@ Meteor.startup(function () { status: "PENDING", events: [], server: !!results.server, - testPath: testPath + testPath: testPath, + test: results.test }; report(name, false); } + // Loop through events, and record status for each test + // Also log result if test has finished _.each(results.events, function (event) { resultSet[name].events.push(event); switch (event.type) { @@ -136,6 +168,7 @@ Meteor.startup(function () { }); }, + // After test completion, log a quick summary function () { if (failed > 0) { log("~~~~~~~ THERE ARE FAILURES ~~~~~~~"); @@ -153,6 +186,43 @@ Meteor.startup(function () { TEST_STATUS.DONE = DONE = true; } }); + + // Also log xUnit output + xunit(''); + _.each(resultSet, function (result, name) { + var classname = result.testPath.join('.').replace(/ /g, '-') + (result.server ? "-server" : "-client"); + var name = result.test.replace(/ /g, '-') + (result.server ? "-server" : "-client"); + var time = ""; + var error = ""; + _.each(result.events, function (event) { + switch (event.type) { + case "finish": + var timeMs = event.timeMs; + if (timeMs !== undefined) { + time = (timeMs / 1000) + ""; + } + break; + case "fail": + var details = event.details || {}; + error = (details.message || '?') + " filename=" + (details.filename || '?') + " line=" + (details.line || '?'); + } + }); + switch (event.status) { + case "FAIL": + error = error || '?'; + break; + case "EXPECTED": + error = "Expected failure"; + break; + } + + xunit(''); + if (error) { + xunit(' ' + escapeXml(error) + ''); + } + xunit(''); + }); + xunit(''); }, ["tinytest"]); });