blob: 6fdea506b3a0e5c51c647fb6ad3e90746138d8a5 [file] [log] [blame]
var __EASE_UnitTest_TestRunner = {
/**
* Execute all unit tests.
*/
run : function() {
this.getUnitTestModule().setThrowOnFailure(true);
var iterator = getScriptEngine().getVariables().entrySet().iterator();
while (iterator.hasNext()) {
var candidateEntry = iterator.next();
var candidate = candidateEntry.getValue();
if (this.isUnitTest(candidate)) {
// this is a unit test class
var testClass = this.getUnitTestModule().addTestClass(candidateEntry.getKey());
if (candidate.hasOwnProperty("__description"))
testClass.setDescription(candidate.__description);
var testcases = new Array();
var testClassSetup = null;
var testClassTeardown = null;
var testSetup = null;
var testTeardown = null;
for (test in candidate) {
var annotations = this.getAnnotations(candidate[test]);
if (annotations.hasOwnProperty("before"))
testSetup = test;
else if (annotations.hasOwnProperty("after"))
testTeardown = test;
else if (annotations.hasOwnProperty("beforeclass"))
testClassSetup = test;
else if (annotations.hasOwnProperty("afterclass"))
testClassTeardown = test;
else if ((annotations.hasOwnProperty("test")) || (test.match(/^test.*/) != null))
testcases[testcases.length] = test;
}
if ((test.length > 0) && (testClassSetup != null))
candidate[testClassSetup]();
for (index in testcases) {
var test = testcases[index];
var annotations = this.getAnnotations(candidate[test]);
this.getUnitTestModule().startTest(test, annotations["description"]);
// register test start location
try {
// only works for Rhino debug engine
var debugView = getScriptEngine().getContext().getDebuggableView(candidate[test]);
var file = org.eclipse.ease.tools.ResourceTools.resolve(debugView.getSourceName());
var script = new org.eclipse.ease.Script("", file, false);
// line numbers are not sorted
var debugFrame = new org.eclipse.ease.debugging.ScriptDebugFrame(script, this
.getFirstLineNumber(debugView.getLineNumbers()), -1);
var stackTrace = new org.eclipse.ease.debugging.ScriptStackTrace();
stackTrace.add(debugFrame);
this.getUnitTestModule().getCurrentTest().setStackTrace(stackTrace);
} catch (e) {
// we could not set the stacktrace for the unit test start location, ignore
}
if (candidate.hasOwnProperty("__ignore")) {
this.getUnitTestModule().ignoreTest(candidate["__ignore"]);
} else if (annotations.hasOwnProperty("ignore")) {
this.getUnitTestModule().ignoreTest(annotations["ignore"]);
} else {
try {
if (testSetup != null)
candidate[testSetup]();
try {
this.getUnitTestModule().setTestTimeout(this.getTimeout(annotations));
// execute the test
candidate[test]();
// check for expected exception
var expectedException = this.getExpectedException(annotations);
if (expectedException != null) {
this.getUnitTestModule().failure(
"Expected exception not thrown: " + expectedException,
this.getUnitTestModule().getCurrentTest().getStackTrace());
}
} catch (e) {
if (this.isAssertion(e)) {
// test failure
try {
this.getUnitTestModule().failure(e.javaException.getMessage(),
getScriptEngine().getExceptionStackTrace());
} catch (e1) {
// no exception stacktrace available
this.getUnitTestModule().failure(e.javaException.getMessage());
}
} else if (this.isExpectedException(annotations, e)) {
// nothing to do, test is pass
} else {
// test error
var message = (typeof (e.javaException) !== 'undefined') ? e.javaException
.getMessage() : e;
try {
this.getUnitTestModule().error(message,
getScriptEngine().getExceptionStackTrace());
} catch (e1) {
// no exception stacktrace available
this.getUnitTestModule().error(message);
}
}
} finally {
try {
if (testTeardown != null)
candidate[testTeardown]();
} catch (e) {
// test setup error
var message = (typeof (e.javaException) !== 'undefined') ? e.javaException
.getMessage() : e;
try {
this.getUnitTestModule().error("Test teardown error: " + message,
getScriptEngine().getExceptionStackTrace());
} catch (e1) {
// no exception stacktrace available
this.getUnitTestModule().error("Test teardown error: " + message);
}
}
}
} catch (e) {
// test setup error
var message = (typeof (e.javaException) !== 'undefined') ? e.javaException.getMessage() : e;
try {
this.getUnitTestModule().error("Test setup error: " + message,
getScriptEngine().getExceptionStackTrace());
} catch (e1) {
// no exception stacktrace available
this.getUnitTestModule().error("Test setup error: " + message);
}
}
}
this.getUnitTestModule().endTest();
}
if ((test.length > 0) && (testClassTeardown != null))
candidate[testClassTeardown]();
this.getUnitTestModule().addTestClass(null);
}
}
},
/**
* Get the lowest number in an unsorted array of line numbers
*
* @param {array}
* lineNumbers - unsorted line numbers of a function
* @return lowest line number
*/
getFirstLineNumber : function(lineNumbers) {
var min = lineNumbers[0];
for (index in lineNumbers) {
if (lineNumbers[index] < min)
min = lineNumbers[index];
}
return min;
},
/**
* Verify that an object is a unit test.
*
* @param {object}
* candidate - object to test
*/
isUnitTest : function(candidate) {
try {
return candidate.hasOwnProperty("__unittest");
} catch (e) {
return false;
}
},
/**
* Get annotations from a method. Annotations are simple string literals
* starting with an '@' at the beginning of the function code.
*
* @param {function}
* method - function to get annotations from
*/
getAnnotations : function(method) {
var annotations = {};
var data = method.toString();
var expression = /@(\w+)(?:\((.*)\)["'])?;?/g;
var match;
do {
match = expression.exec(data);
if (match) {
annotations[match[1].toLowerCase()] = match[2];
}
} while (match);
return annotations;
},
/**
* Check if a thrown exception was expected by the provided test function.
*
* @param {array}
* annotations - function annotations
* @param {exception}
* e - thrown exception
*/
isExpectedException : function(annotations, e) {
try {
if (this.isJavaException(e))
return (e.javaException.getClass().getName() == this.getExpectedException(annotations));
else if (e instanceof java.lang.Throwable)
return (e.getClass().getName() == this.getExpectedException(annotations));
} catch (e1) {
}
return false;
},
/**
* Extract expected exception type from given method annotations.
*
* @param {array}
* annotations - method annotations
* @return expected java exception class name or <code>null</code>
*/
getExpectedException : function(annotations) {
if (annotations.hasOwnProperty("expect"))
return annotations["expect"];
return null;
},
/**
* Validate if an exception is actually a wrapped java exception.
*
* @param {Exception}
* e - exception to query
* @return <code>true</code> when exception is a wrapped java exception
*/
isJavaException : function(e) {
try {
return (typeof (e.javaException) !== 'undefined');
} catch (e1) {
}
return false;
},
/**
* Validate if an exception is actually a test assertion.
*
* @param {Exception}
* e - exception to query
* @return <code>true</code> when exception is an assertion
*/
isAssertion : function(e) {
return this.isJavaException(e)
&& e.javaException.getClass().equals(org.eclipse.ease.lang.unittest.AssertionException);
},
/**
* Get test timeout in [ms].
*
* @param {array}
* annotations - method annotations
* @return timeout in milliseconds or 0
*/
getTimeout : function(annotations) {
if (annotations.hasOwnProperty("timeout"))
return parseInt(annotations["timeout"]);
return 0;
},
/**
* Get instance of EASE unittest module. Will be loaded on demand.
*
* @return unittest module
*/
getUnitTestModule : function() {
var module = getScriptEngine().getVariable("__MOD_org_eclipse_ease_lang_unittest_UnitTestModule");
if (module == null) {
loadModule("/Unittest", true);
module = getScriptEngine().getVariable("__MOD_org_eclipse_ease_lang_unittest_UnitTestModule");
}
return module;
},
}
// execute test runner
__EASE_UnitTest_TestRunner.run();