Upload and Begin
This commit is contained in:
391
jsunity-0.6.js
Normal file
391
jsunity-0.6.js
Normal file
@ -0,0 +1,391 @@
|
||||
//<%
|
||||
/**
|
||||
* jsUnity Universal JavaScript Testing Framework v0.6
|
||||
* http://jsunity.com/
|
||||
*
|
||||
* Copyright (c) 2009 Ates Goral
|
||||
* Licensed under the MIT license.
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
jsUnity = (function () {
|
||||
function fmt(str) {
|
||||
var a = Array.prototype.slice.call(arguments, 1);
|
||||
return str.replace(/\?/g, function () { return a.shift(); });
|
||||
}
|
||||
|
||||
function hash(v) {
|
||||
if (v instanceof Object) {
|
||||
var arr = [];
|
||||
|
||||
for (var p in v) {
|
||||
arr.push(p);
|
||||
arr.push(hash(v[p]));
|
||||
}
|
||||
|
||||
return arr.join("#");
|
||||
} else {
|
||||
return String(v);
|
||||
}
|
||||
}
|
||||
|
||||
var defaultAssertions = {
|
||||
assertException: function (fn, message) {
|
||||
try {
|
||||
fn instanceof Function && fn();
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw fmt("?: (?) does not raise an exception or not a function",
|
||||
message || "assertException", fn);
|
||||
},
|
||||
|
||||
assertTrue: function (actual, message) {
|
||||
if (!actual) {
|
||||
throw fmt("?: (?) does not evaluate to true",
|
||||
message || "assertTrue", actual);
|
||||
}
|
||||
},
|
||||
|
||||
assertFalse: function (actual, message) {
|
||||
if (actual) {
|
||||
throw fmt("?: (?) does not evaluate to false",
|
||||
message || "assertFalse", actual);
|
||||
}
|
||||
},
|
||||
|
||||
assertIdentical: function (expected, actual, message) {
|
||||
if (expected !== actual) {
|
||||
throw fmt("?: (?) is not identical to (?)",
|
||||
message || "assertIdentical", actual, expected);
|
||||
}
|
||||
},
|
||||
|
||||
assertNotIdentical: function (expected, actual, message) {
|
||||
if (expected === actual) {
|
||||
throw fmt("?: (?) is identical to (?)",
|
||||
message || "assertNotIdentical", actual, expected);
|
||||
}
|
||||
},
|
||||
|
||||
assertEqual: function (expected, actual, message) {
|
||||
if (hash(expected) != hash(actual)) {
|
||||
throw fmt("?: (?) is not equal to (?)",
|
||||
message || "assertEqual", actual, expected);
|
||||
}
|
||||
},
|
||||
|
||||
assertNotEqual: function (expected, actual, message) {
|
||||
if (hash(expected) == hash(actual)) {
|
||||
throw fmt("?: (?) is equal to (?)",
|
||||
message || "assertNotEqual", actual, expected);
|
||||
}
|
||||
},
|
||||
|
||||
assertMatch: function (re, actual, message) {
|
||||
if (!re.test(actual)) {
|
||||
throw fmt("?: (?) does not match (?)",
|
||||
message || "assertMatch", actual, re);
|
||||
}
|
||||
},
|
||||
|
||||
assertNotMatch: function (re, actual, message) {
|
||||
if (re.test(actual)) {
|
||||
throw fmt("?: (?) matches (?)",
|
||||
message || "assertNotMatch", actual, re);
|
||||
}
|
||||
},
|
||||
|
||||
assertTypeOf: function (typ, actual, message) {
|
||||
if (typeof actual !== typ) {
|
||||
throw fmt("?: (?) is not of type (?)",
|
||||
message || "assertTypeOf", actual, typ);
|
||||
}
|
||||
},
|
||||
|
||||
assertNotTypeOf: function (typ, actual, message) {
|
||||
if (typeof actual === typ) {
|
||||
throw fmt("?: (?) is of type (?)",
|
||||
message || "assertNotTypeOf", actual, typ);
|
||||
}
|
||||
},
|
||||
|
||||
assertInstanceOf: function (cls, actual, message) {
|
||||
if (!(actual instanceof cls)) {
|
||||
throw fmt("?: (?) is not an instance of (?)",
|
||||
message || "assertInstanceOf", actual, cls);
|
||||
}
|
||||
},
|
||||
|
||||
assertNotInstanceOf: function (cls, actual, message) {
|
||||
if (actual instanceof cls) {
|
||||
throw fmt("?: (?) is an instance of (?)",
|
||||
message || "assertNotInstanceOf", actual, cls);
|
||||
}
|
||||
},
|
||||
|
||||
assertNull: function (actual, message) {
|
||||
if (actual !== null) {
|
||||
throw fmt("?: (?) is not null",
|
||||
message || "assertNull", actual);
|
||||
}
|
||||
},
|
||||
|
||||
assertNotNull: function (actual, message) {
|
||||
if (actual === null) {
|
||||
throw fmt("?: (?) is null",
|
||||
message || "assertNotNull", actual);
|
||||
}
|
||||
},
|
||||
|
||||
assertUndefined: function (actual, message) {
|
||||
if (actual !== undefined) {
|
||||
throw fmt("?: (?) is not undefined",
|
||||
message || "assertUndefined", actual);
|
||||
}
|
||||
},
|
||||
|
||||
assertNotUndefined: function (actual, message) {
|
||||
if (actual === undefined) {
|
||||
throw fmt("?: (?) is undefined",
|
||||
message || "assertNotUndefined", actual);
|
||||
}
|
||||
},
|
||||
|
||||
assertNaN: function (actual, message) {
|
||||
if (!isNaN(actual)) {
|
||||
throw fmt("?: (?) is not NaN",
|
||||
message || "assertNaN", actual);
|
||||
}
|
||||
},
|
||||
|
||||
assertNotNaN: function (actual, message) {
|
||||
if (isNaN(actual)) {
|
||||
throw fmt("?: (?) is NaN",
|
||||
message || "assertNotNaN", actual);
|
||||
}
|
||||
},
|
||||
|
||||
fail: function (message) {
|
||||
throw message || "fail";
|
||||
}
|
||||
};
|
||||
|
||||
function plural(cnt, unit) {
|
||||
return cnt + " " + unit + (cnt == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
function splitFunction(fn) {
|
||||
var tokens =
|
||||
/^[\s\r\n]*function[\s\r\n]*([^\(\s\r\n]*?)[\s\r\n]*\([^\)\s\r\n]*\)[\s\r\n]*\{((?:[^}]*\}?)+)\}[\s\r\n]*$/
|
||||
.exec(fn);
|
||||
|
||||
if (!tokens) {
|
||||
throw "Invalid function.";
|
||||
}
|
||||
|
||||
return {
|
||||
name: tokens[1].length ? tokens[1] : undefined,
|
||||
body: tokens[2]
|
||||
};
|
||||
}
|
||||
|
||||
var probeOutside = function () {
|
||||
try {
|
||||
return eval(
|
||||
[ "typeof ", " === \"function\" && ", "" ].join(arguments[0]));
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
function parseSuiteString(str) {
|
||||
var obj = {};
|
||||
|
||||
var probeInside = new Function(
|
||||
splitFunction(probeOutside).body + str);
|
||||
|
||||
var tokenRe = /(\w+)/g; // todo: wiser regex
|
||||
var tokens;
|
||||
|
||||
while ((tokens = tokenRe.exec(str))) {
|
||||
var token = tokens[1];
|
||||
var fn;
|
||||
|
||||
if (!obj[token]
|
||||
&& (fn = probeInside(token))
|
||||
&& fn != probeOutside(token)) {
|
||||
|
||||
obj[token] = fn;
|
||||
}
|
||||
}
|
||||
|
||||
return parseSuiteObject(obj);
|
||||
}
|
||||
|
||||
function parseSuiteFunction(fn) {
|
||||
var fnParts = splitFunction(fn);
|
||||
var suite = parseSuiteString(fnParts.body);
|
||||
|
||||
suite.suiteName = fnParts.name;
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
function parseSuiteArray(tests) {
|
||||
var obj = {};
|
||||
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
var item = tests[i];
|
||||
|
||||
if (!obj[item]) {
|
||||
switch (typeof item) {
|
||||
case "function":
|
||||
var fnParts = splitFunction(item);
|
||||
obj[fnParts.name] = item;
|
||||
break;
|
||||
case "string":
|
||||
var fn;
|
||||
|
||||
if (fn = probeOutside(item)) {
|
||||
obj[item] = fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parseSuiteObject(obj);
|
||||
}
|
||||
|
||||
function parseSuiteObject(obj) {
|
||||
var suite = new jsUnity.TestSuite(obj.suiteName, obj);
|
||||
|
||||
for (var name in obj) {
|
||||
if (obj.hasOwnProperty(name)) {
|
||||
var fn = obj[name];
|
||||
|
||||
if (typeof fn === "function") {
|
||||
if (/^test/.test(name)) {
|
||||
suite.tests.push({ name: name, fn: fn });
|
||||
} else if (/^setUp|tearDown$/.test(name)) {
|
||||
suite[name] = fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
return {
|
||||
TestSuite: function (suiteName, scope) {
|
||||
this.suiteName = suiteName;
|
||||
this.scope = scope;
|
||||
this.tests = [];
|
||||
this.setUp = undefined;
|
||||
this.tearDown = undefined;
|
||||
},
|
||||
|
||||
TestResults: function () {
|
||||
this.suiteName = undefined;
|
||||
this.total = 0;
|
||||
this.passed = 0;
|
||||
this.failed = 0;
|
||||
this.duration = 0;
|
||||
},
|
||||
|
||||
assertions: defaultAssertions,
|
||||
|
||||
env: {
|
||||
defaultScope: this,
|
||||
|
||||
getDate: function () {
|
||||
return new Date();
|
||||
}
|
||||
},
|
||||
|
||||
attachAssertions: function (scope) {
|
||||
scope = scope || this.env.defaultScope;
|
||||
|
||||
for (var fn in jsUnity.assertions) {
|
||||
scope[fn] = jsUnity.assertions[fn];
|
||||
}
|
||||
},
|
||||
|
||||
log: function () {},
|
||||
|
||||
error: function (s) { this.log("[ERROR] " + s); },
|
||||
|
||||
compile: function (v) {
|
||||
if (v instanceof jsUnity.TestSuite) {
|
||||
return v;
|
||||
} else if (v instanceof Function) {
|
||||
return parseSuiteFunction(v);
|
||||
} else if (v instanceof Array) {
|
||||
return parseSuiteArray(v);
|
||||
} else if (v instanceof Object) {
|
||||
return parseSuiteObject(v);
|
||||
} else if (typeof v === "string") {
|
||||
return parseSuiteString(v);
|
||||
} else {
|
||||
throw "Argument must be a function, array, object, string or "
|
||||
+ "TestSuite instance.";
|
||||
}
|
||||
},
|
||||
|
||||
run: function () {
|
||||
var results = new jsUnity.TestResults();
|
||||
|
||||
var suiteNames = [];
|
||||
var start = jsUnity.env.getDate();
|
||||
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
try {
|
||||
var suite = jsUnity.compile(arguments[i]);
|
||||
} catch (e) {
|
||||
this.error("Invalid test suite: " + e);
|
||||
return false;
|
||||
}
|
||||
|
||||
var cnt = suite.tests.length;
|
||||
|
||||
this.log("Running "
|
||||
+ (suite.suiteName || "unnamed test suite"));
|
||||
this.log(plural(cnt, "test") + " found");
|
||||
|
||||
suiteNames.push(suite.suiteName);
|
||||
results.total += cnt;
|
||||
|
||||
for (var j = 0; j < cnt; j++) {
|
||||
var test = suite.tests[j];
|
||||
|
||||
try {
|
||||
suite.setUp && suite.setUp();
|
||||
test.fn.call(suite.scope);
|
||||
suite.tearDown && suite.tearDown();
|
||||
|
||||
results.passed++;
|
||||
|
||||
this.log("[PASSED] " + test.name);
|
||||
} catch (e) {
|
||||
suite.tearDown && suite.tearDown();
|
||||
|
||||
this.log("[FAILED] " + test.name + ": " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
results.suiteName = suiteNames.join(",");
|
||||
results.failed = results.total - results.passed;
|
||||
results.duration = jsUnity.env.getDate() - start;
|
||||
|
||||
this.log(plural(results.passed, "test") + " passed");
|
||||
this.log(plural(results.failed, "test") + " failed");
|
||||
this.log(plural(results.duration, "millisecond") + " elapsed");
|
||||
|
||||
return results;
|
||||
}
|
||||
};
|
||||
})();
|
||||
//%>
|
Reference in New Issue
Block a user