Commit e9df8be7 e9df8be7e1d4e27602db68cda987c87f124ef4f3 by Nicolas Perriault

added XUnit formatted test results export

1 parent b234b6de
...@@ -901,14 +901,15 @@ ...@@ -901,14 +901,15 @@
901 * 901 *
902 */ 902 */
903 phantom.Casper.Tester = function(casper, options) { 903 phantom.Casper.Tester = function(casper, options) {
904 options = typeof options === "object" || {}; 904 this.options = typeof options === "object" || {};
905 if (!casper instanceof phantom.Casper) { 905 if (!casper instanceof phantom.Casper) {
906 throw "phantom.Casper.Tester needs a phantom.Casper instance"; 906 throw "phantom.Casper.Tester needs a phantom.Casper instance";
907 } 907 }
908 908
909 // locals 909 // locals
910 var PASS = options.PASS || "PASS"; 910 var exporter = new phantom.Casper.XUnitExporter();
911 var FAIL = options.FAIL || "FAIL"; 911 var PASS = this.options.PASS || "PASS";
912 var FAIL = this.options.FAIL || "FAIL";
912 913
913 // properties 914 // properties
914 this.testResults = { 915 this.testResults = {
...@@ -928,10 +929,12 @@ ...@@ -928,10 +929,12 @@
928 if (condition === true) { 929 if (condition === true) {
929 style = 'INFO'; 930 style = 'INFO';
930 this.testResults.passed++; 931 this.testResults.passed++;
932 exporter.addSuccess("unknown", message);
931 } else { 933 } else {
932 status = FAIL; 934 status = FAIL;
933 style = 'RED_BAR'; 935 style = 'RED_BAR';
934 this.testResults.failed++; 936 this.testResults.failed++;
937 exporter.addFailure("unknown", message, 'test failed', "assert");
935 } 938 }
936 casper.echo([this.colorize(status, style), this.formatMessage(message)].join(' ')); 939 casper.echo([this.colorize(status, style), this.formatMessage(message)].join(' '));
937 }; 940 };
...@@ -947,11 +950,13 @@ ...@@ -947,11 +950,13 @@
947 if (expected === testValue) { 950 if (expected === testValue) {
948 casper.echo(this.colorize(PASS, 'INFO') + ' ' + this.formatMessage(message)); 951 casper.echo(this.colorize(PASS, 'INFO') + ' ' + this.formatMessage(message));
949 this.testResults.passed++; 952 this.testResults.passed++;
953 exporter.addSuccess("unknown", message);
950 } else { 954 } else {
951 casper.echo(this.colorize(FAIL, 'RED_BAR') + ' ' + this.formatMessage(message, 'WARNING')); 955 casper.echo(this.colorize(FAIL, 'RED_BAR') + ' ' + this.formatMessage(message, 'WARNING'));
952 this.comment(' got: ' + testValue); 956 this.comment(' got: ' + testValue);
953 this.comment(' expected: ' + expected); 957 this.comment(' expected: ' + expected);
954 this.testResults.failed++; 958 this.testResults.failed++;
959 exporter.addFailure("unknown", message, "test failed; expected: " + expected + "; got: " + testValue, "assertEquals");
955 } 960 }
956 }; 961 };
957 962
...@@ -1076,7 +1081,8 @@ ...@@ -1076,7 +1081,8 @@
1076 * 1081 *
1077 * @param Boolean exit 1082 * @param Boolean exit
1078 */ 1083 */
1079 this.renderResults = function(exit, status) { 1084 this.renderResults = function(exit, status, save) {
1085 save = typeof save === "string" ? save : this.options.save;
1080 var total = this.testResults.passed + this.testResults.failed, status, style, result; 1086 var total = this.testResults.passed + this.testResults.failed, status, style, result;
1081 if (this.testResults.failed > 0) { 1087 if (this.testResults.failed > 0) {
1082 status = FAIL; 1088 status = FAIL;
...@@ -1090,12 +1096,62 @@ ...@@ -1090,12 +1096,62 @@
1090 result += new Array(80 - result.length + 1).join(' '); 1096 result += new Array(80 - result.length + 1).join(' ');
1091 } 1097 }
1092 casper.echo(this.colorize(result, style)); 1098 casper.echo(this.colorize(result, style));
1099 if (save && typeof(require) === "function") {
1100 try {
1101 require('fs').write(save, exporter.getXML(), 'w');
1102 casper.echo('result log stored in ' + save, 'INFO');
1103 } catch (e) {
1104 casper.echo('unable to write results to ' + save + '; ' + e, 'ERROR');
1105 }
1106 }
1093 if (exit === true) { 1107 if (exit === true) {
1094 casper.exit(status || 0); 1108 casper.exit(status || 0);
1095 } 1109 }
1096 }; 1110 };
1097 }; 1111 };
1098 1112
1113 phantom.Casper.XUnitExporter = function() {
1114 var node = function(name, attributes) {
1115 var node = document.createElement(name);
1116 for (attrName in attributes) {
1117 var value = attributes[attrName];
1118 if (attributes.hasOwnProperty(attrName) && typeof attrName === "string") {
1119 node.setAttribute(attrName, value);
1120 }
1121 }
1122 return node;
1123 };
1124
1125 var xml = node('testsuite');
1126 xml.toString = function() {
1127 return this.outerHTML; // ouch
1128 };
1129
1130 this.addSuccess = function(classname, name) {
1131 xml.appendChild(node('testcase', {
1132 classname: classname,
1133 name: name
1134 }));
1135 };
1136
1137 this.addFailure = function(classname, name, message, type) {
1138 var fnode = node('testcase', {
1139 classname: classname,
1140 name: name
1141 });
1142 var failure = node('failure', {
1143 type: type || "unknown"
1144 });
1145 failure.appendChild(document.createTextNode(message || "no message left"));
1146 fnode.appendChild(failure);
1147 xml.appendChild(fnode);
1148 };
1149
1150 this.getXML = function() {
1151 return xml;
1152 }
1153 };
1154
1099 /** 1155 /**
1100 * Creates a new WebPage instance for Casper use. 1156 * Creates a new WebPage instance for Casper use.
1101 * 1157 *
......
...@@ -4,11 +4,17 @@ var casper = new phantom.Casper({ ...@@ -4,11 +4,17 @@ var casper = new phantom.Casper({
4 faultTolerant: false 4 faultTolerant: false
5 }); 5 });
6 6
7 var save = null;
8
7 phantom.args.forEach(function(arg) { 9 phantom.args.forEach(function(arg) {
8 var debugMatch = /--loglevel=(\w+)/.exec(arg); 10 var debugMatch = /--loglevel=(\w+)/.exec(arg);
9 if (debugMatch) { 11 if (debugMatch) {
10 casper.options.logLevel = debugMatch[1]; 12 casper.options.logLevel = debugMatch[1];
11 } 13 }
14 var saveMatch = /--save=(.*)(\s|)/.exec(arg);
15 if (saveMatch) {
16 save = saveMatch[1];
17 }
12 }); 18 });
13 19
14 // Casper#log() 20 // Casper#log()
...@@ -93,7 +99,15 @@ casper.then(function(self) { ...@@ -93,7 +99,15 @@ casper.then(function(self) {
93 self.test.assertUrlMatch(/topic=bar/, 'fill() select field was submitted'); 99 self.test.assertUrlMatch(/topic=bar/, 'fill() select field was submitted');
94 }); 100 });
95 101
102 // Casper.XUnitExporter
103 casper.test.comment('phantom.Casper.XUnitExporter');
104 xunit = new phantom.Casper.XUnitExporter();
105 xunit.addSuccess('foo', 'bar');
106 casper.test.assertMatch(xunit.getXML(), /<testcase classname="foo" name="bar"/, 'addSuccess() adds a successful testcase');
107 xunit.addFailure('bar', 'baz', 'wrong', 'chucknorriz');
108 casper.test.assertMatch(xunit.getXML(), /<testcase classname="bar" name="baz"><failure type="chucknorriz">wrong/, 'addFailure() adds a failed testcase');
109
96 casper.run(function(self) { 110 casper.run(function(self) {
97 self.test.assert(self.result.log.length > 0, 'log() logged messages'); 111 self.test.assert(self.result.log.length > 0, 'log() logged messages');
98 self.test.renderResults(true); 112 self.test.renderResults(true, 0, save);
99 }); 113 });
......