1 // # $Id: Kinetic.pm 1493 2005-04-07 19:20:18Z theory $
4 if (typeof self != 'undefined') {
6 if (typeof Test == 'undefined') Test = {PLATFORM: 'browser'};
7 else Test.PLATFORM = 'browser';
8 } else if (typeof _player != 'undefined'){
10 if (typeof _global.Test != "object") _global.Test = {PLATFORM: 'director'};
11 else _global.Test.PLATFORM = 'director';
13 throw new Error("Test.Harness does not support your platform");
16 Test.Harness = function () {};
17 Test.Harness.VERSION = '0.11';
18 Test.Harness.Done = 0;
21 Test.Harness.LF = typeof document != "undefined"
22 && typeof document.all != "undefined"
26 Test.Harness.prototype.isDone = Test.Harness.isDone;
30 bonus Number of individual todo tests unexpectedly passed
31 ran Number of individual tests ran
32 ok Number of individual tests passed
33 subSkipped Number of individual tests skipped
34 todo Number of individual todo tests
36 files Number of test files ran
37 good Number of test files passed
38 bad Number of test files failed
39 tests Number of test files originally given
40 skipped Number of test files skipped
44 Test.Harness.prototype.bonus = 0;
45 Test.Harness.prototype.ran = 0;
46 Test.Harness.prototype.ok = 0;
47 Test.Harness.prototype.subSkipped = 0;
48 Test.Harness.prototype.todo = 0;
49 Test.Harness.prototype.files = 0;
50 Test.Harness.prototype.good = 0;
51 Test.Harness.prototype.bad = 0;
52 Test.Harness.prototype.tests = 0;
53 Test.Harness.prototype.skipped = 0;
54 Test.Harness.prototype.failures = [];
56 Test.Harness.runTests = function () {
57 // XXX Can't handle inheritance, right? Or can we?
58 var harness = new Test.Harness();
59 harness.runTests.apply(harness, arguments);
62 Test.Harness.prototype.outFileNames = function (files) {
64 for (var i = 0; i < files.length; i++) {
65 if (files[i].length > len) len = files[i].length;
69 for (var i = 0; i < files.length; i++) {
70 var outName = files[i];
71 var add = len - files[i].length;
72 // Where is Perl's x operator when I need it??
73 for (var j = 0; j < add; j++) {
81 Test.Harness.prototype.outputResults = function (test, file, fn, attrs) {
83 this.ran += test.TestResults.length;
87 total: test.expectedTests,
92 if (test.TestResults.length) {
95 for (var i = 0; i < test.TestResults.length; i++) {
97 if (test.TestResults[i].ok) {
100 if (test.TestResults[i].type == 'todo') {
101 // Handle unexpected pass.
102 if (test.TestResults[i].actualOK) this.bonus++;
104 } else if (test.TestResults[i].type == 'skip') this.subSkipped++;
106 if (test.TestResults[i].type == 'todo') {
111 track.failList.push(i + 1);
113 ok = "not ok"; // XXX Need to handle TODO and TODO Skipped.
116 if (!pass || attrs.verbose) fn(test.TestResults[i].output);
121 fn("ok" + Test.Harness.LF);
124 var err = "NOK # Failed ";
125 if (track.failList.length == 1) {
126 err += "test " + track.failList[0];
128 err += "tests " + this._failList(track.failList);
130 fn(err + " in " + file + Test.Harness.LF);
132 } else if (test.SkipAll){
133 // All tests skipped.
136 fn("1..0 # Skip 1" + Test.Harness.LF);
138 // Wha happened? Tests ran, but no results!
141 fn("FAILED before any test output arrived" + Test.Harness.LF);
143 if (track.failList.length) this.failures.push(track);
146 Test.Harness.prototype._allOK = function () {
147 return this.bad == 0 && (this.ran || this.skipped) ? true : false;
150 Test.Harness.prototype.outputSummary = function (fn, time) {
151 var bonusmsg = this._bonusmsg();
154 fn("All tests successful" + bonusmsg + '.' + Test.Harness.LF);
155 } else if (!this.tests) {
156 fn("FAILED—no tests were run for some reason." + Test.Harness.LF);
157 } else if (!this.ran) {
158 var blurb = this.tests == 1 ? "file" : "files";
159 fn("FAILED—" + this.tests + " test " + blurb + " could be run, "
160 + "alas—no output ever seen." + Test.Harness.LF);
162 pct = this.good / this.tests * 100;
163 var pctOK = 100 * this.ok / this.ran;
164 var subpct = (this.ran - this.ok) + "/" + this.ran
165 + " subtests failed, " + pctOK.toPrecision(4) + "% okay.";
168 bonusmsg = bonusmsg.replace(/^,?\s*/, '');
169 if (bonusmsg) fn(bonusmsg + '.' + Test.Harness.LF);
170 fn("Failed " + this.bad + "/" + this.tests + " test scripts, "
171 + pct.toPrecision(4) + "% okay. " + subpct + Test.Harness.LF);
173 this.formatFailures(fn);
176 fn("Files=" + this.tests + ", Tests=" + this.ran + ", " + (time / 1000)
177 + " seconds" + Test.Harness.LF);
180 Test.Harness.prototype.formatFailures = function () {
182 var failedStr = "Failed Test";
183 var middleStr = " Total Fail Failed ";
184 var listStr = "List of Failed";
187 // Figure out our longest name string for formatting purposes.
188 var maxNamelen = failedStr.length;
189 for (var i = 0; i < this.failures.length; i++) {
190 var len = this.failures[i].length;
191 if (len > maxNamelen) maxNamelen = len;
194 var listLen = cols - middleStr.length - maxNamelen.length;
195 if (listLen < listStr.length) {
196 listLen = listStr.length;
197 maxNamelen = cols - middleStr.length - listLen;
198 if (maxNamelen < failedStr.length) {
199 maxNamelen = failedStr.length;
200 cols = maxNamelen + middleStr.length + listLen;
205 if (out.length < maxNamelen) {
206 for (var j = out.length; j < maxNameLength; j++) {
210 out += ' ' + middleStr;
211 // XXX Need to finish implementing the text-only version of the failures
215 Test.Harness.prototype._bonusmsg = function () {
218 bonusmsg = (" (" + this.bonus + " subtest" + (this.bonus > 1 ? 's' : '')
219 + " UNEXPECTEDLY SUCCEEDED)");
223 bonusmsg += ", " + this.skipped + " test"
224 + (this.skipped != 1 ? 's' : '');
225 if (this.subSkipped) {
226 bonusmsg += " and " + this.subSkipped + " subtest"
227 + (this.subSkipped != 1 ? 's' : '');
229 bonusmsg += ' skipped';
230 } else if (this.subSkipped) {
231 bonusmsg += ", " + this.subSkipped + " subtest"
232 + (this.subSkipped != 1 ? 's' : '') + " skipped";
238 Test.Harness.prototype._failList = function (fails) {
242 for (var i = 0; i < fails.length; i++) {
244 // We're in a series of numbers.
245 if (fails[i] - 1 == last) {
246 // We're still in it.
250 list[list.length-1] += dash + last;
255 } else if (fails[i] - 1 == last) {
256 // We're in a new series.
260 // Not in a sequence.
265 if (dash) list[list.length-1] += dash + last;
266 return list.join(' ');