jquery/test/lib/Test/Harness.js
2006-08-13 15:24:52 +00:00

267 lines
8.4 KiB
JavaScript

// # $Id: Kinetic.pm 1493 2005-04-07 19:20:18Z theory $
// Set up namespace.
if (typeof self != 'undefined') {
//Browser
if (typeof Test == 'undefined') Test = {PLATFORM: 'browser'};
else Test.PLATFORM = 'browser';
} else if (typeof _player != 'undefined'){
//Director
if (typeof _global.Test != "object") _global.Test = {PLATFORM: 'director'};
else _global.Test.PLATFORM = 'director';
} else {
throw new Error("Test.Harness does not support your platform");
}
Test.Harness = function () {};
Test.Harness.VERSION = '0.11';
Test.Harness.Done = 0;
// Stoopid IE.
Test.Harness.LF = typeof document != "undefined"
&& typeof document.all != "undefined"
? "\r"
: "\n";
Test.Harness.prototype.isDone = Test.Harness.isDone;
/*
bonus Number of individual todo tests unexpectedly passed
ran Number of individual tests ran
ok Number of individual tests passed
subSkipped Number of individual tests skipped
todo Number of individual todo tests
files Number of test files ran
good Number of test files passed
bad Number of test files failed
tests Number of test files originally given
skipped Number of test files skipped
*/
Test.Harness.prototype.bonus = 0;
Test.Harness.prototype.ran = 0;
Test.Harness.prototype.ok = 0;
Test.Harness.prototype.subSkipped = 0;
Test.Harness.prototype.todo = 0;
Test.Harness.prototype.files = 0;
Test.Harness.prototype.good = 0;
Test.Harness.prototype.bad = 0;
Test.Harness.prototype.tests = 0;
Test.Harness.prototype.skipped = 0;
Test.Harness.prototype.failures = [];
Test.Harness.runTests = function () {
// XXX Can't handle inheritance, right? Or can we?
var harness = new Test.Harness();
harness.runTests.apply(harness, arguments);
};
Test.Harness.prototype.outFileNames = function (files) {
var len = 0;
for (var i = 0; i < files.length; i++) {
if (files[i].length > len) len = files[i].length;
}
len += 3;
var ret = [];
for (var i = 0; i < files.length; i++) {
var outName = files[i];
var add = len - files[i].length;
// Where is Perl's x operator when I need it??
for (var j = 0; j < add; j++) {
outName += '.';
}
ret.push(outName);
}
return ret;
};
Test.Harness.prototype.outputResults = function (test, file, fn, attrs) {
this.tests++;
this.ran += test.TestResults.length;
var fails = [];
var track = {
fn: file,
total: test.expectedTests,
ok: 0,
failList: []
};
if (test.TestResults.length) {
this.files++;
var pass = true;
for (var i = 0; i < test.TestResults.length; i++) {
var ok = "ok";
if (test.TestResults[i].ok) {
this.ok++;
track.ok++
if (test.TestResults[i].type == 'todo') {
// Handle unexpected pass.
if (test.TestResults[i].actualOK) this.bonus++;
this.todo ++;
} else if (test.TestResults[i].type == 'skip') this.subSkipped++;
} else {
if (test.TestResults[i].type == 'todo') {
// Expected failure.
this.todo++;
} else {
pass = false;
track.failList.push(i + 1);
}
ok = "not ok"; // XXX Need to handle TODO and TODO Skipped.
}
if (!pass || attrs.verbose) fn(test.TestResults[i].output);
}
if (pass) {
this.good++;
fn("ok" + Test.Harness.LF);
} else {
this.bad++;
var err = "NOK # Failed ";
if (track.failList.length == 1) {
err += "test " + track.failList[0];
} else {
err += "tests " + this._failList(track.failList);
}
fn(err + " in " + file + Test.Harness.LF);
}
} else if (test.SkipAll){
// All tests skipped.
this.skipped++;
this.good++;
fn("1..0 # Skip 1" + Test.Harness.LF);
} else {
// Wha happened? Tests ran, but no results!
this.files++;
this.bad++;
fn("FAILED before any test output arrived" + Test.Harness.LF);
}
if (track.failList.length) this.failures.push(track);
};
Test.Harness.prototype._allOK = function () {
return this.bad == 0 && (this.ran || this.skipped) ? true : false;
};
Test.Harness.prototype.outputSummary = function (fn, time) {
var bonusmsg = this._bonusmsg();
var pct;
if (this._allOK()) {
fn("All tests successful" + bonusmsg + '.' + Test.Harness.LF);
} else if (!this.tests) {
fn("FAILED—no tests were run for some reason." + Test.Harness.LF);
} else if (!this.ran) {
var blurb = this.tests == 1 ? "file" : "files";
fn("FAILED—" + this.tests + " test " + blurb + " could be run, "
+ "alas—no output ever seen." + Test.Harness.LF);
} else {
pct = this.good / this.tests * 100;
var pctOK = 100 * this.ok / this.ran;
var subpct = (this.ran - this.ok) + "/" + this.ran
+ " subtests failed, " + pctOK.toPrecision(4) + "% okay.";
if (this.bad) {
bonusmsg = bonusmsg.replace(/^,?\s*/, '');
if (bonusmsg) fn(bonusmsg + '.' + Test.Harness.LF);
fn("Failed " + this.bad + "/" + this.tests + " test scripts, "
+ pct.toPrecision(4) + "% okay. " + subpct + Test.Harness.LF);
}
this.formatFailures(fn);
}
fn("Files=" + this.tests + ", Tests=" + this.ran + ", " + (time / 1000)
+ " seconds" + Test.Harness.LF);
};
Test.Harness.prototype.formatFailures = function () {
var table = '';
var failedStr = "Failed Test";
var middleStr = " Total Fail Failed ";
var listStr = "List of Failed";
var cols = 80;
// Figure out our longest name string for formatting purposes.
var maxNamelen = failedStr.length;
for (var i = 0; i < this.failures.length; i++) {
var len = this.failures[i].length;
if (len > maxNamelen) maxNamelen = len;
}
var listLen = cols - middleStr.length - maxNamelen.length;
if (listLen < listStr.length) {
listLen = listStr.length;
maxNamelen = cols - middleStr.length - listLen;
if (maxNamelen < failedStr.length) {
maxNamelen = failedStr.length;
cols = maxNamelen + middleStr.length + listLen;
}
}
var out = failedStr;
if (out.length < maxNamelen) {
for (var j = out.length; j < maxNameLength; j++) {
out += ' ';
}
}
out += ' ' + middleStr;
// XXX Need to finish implementing the text-only version of the failures
// table.
};
Test.Harness.prototype._bonusmsg = function () {
var bonusmsg = '';
if (this.bonus) {
bonusmsg = (" (" + this.bonus + " subtest" + (this.bonus > 1 ? 's' : '')
+ " UNEXPECTEDLY SUCCEEDED)");
}
if (this.skipped) {
bonusmsg += ", " + this.skipped + " test"
+ (this.skipped != 1 ? 's' : '');
if (this.subSkipped) {
bonusmsg += " and " + this.subSkipped + " subtest"
+ (this.subSkipped != 1 ? 's' : '');
}
bonusmsg += ' skipped';
} else if (this.subSkipped) {
bonusmsg += ", " + this.subSkipped + " subtest"
+ (this.subSkipped != 1 ? 's' : '') + " skipped";
}
return bonusmsg;
}
Test.Harness.prototype._failList = function (fails) {
var last = -1;
var dash = '';
var list = [];
for (var i = 0; i < fails.length; i++) {
if (dash) {
// We're in a series of numbers.
if (fails[i] - 1 == last) {
// We're still in it.
last = fails[i];
} else {
// End of the line.
list[list.length-1] += dash + last;
last = -1;
list.push(fails[i]);
dash = '';
}
} else if (fails[i] - 1 == last) {
// We're in a new series.
last = fails[i];
dash = '-';
} else {
// Not in a sequence.
list.push(fails[i]);
last = fails[i];
}
}
if (dash) list[list.length-1] += dash + last;
return list.join(' ');
}